Gaia is a Go CLI built around a minimal kernel. The kernel only bootstraps the app and manages plugins. Every feature is implemented as a plugin.
go build ./...
./gaia --helpDefault config location: ~/.config/gaia/config.yaml (or ~/.config/gaia/config.yml)
Kernel-owned keys:
plugins.enabled: list of plugin IDs to force-enableplugins.disabled: list of plugin IDs to force-disableconfig.validation:strict,warn, oroff(default:warn)
Plugin keys must be namespaced as <plugin>.* and are validated against each plugin’s schema.
Plugin-specific config files live at ~/.config/gaia/plugins/<plugin>.yaml.
Example:
plugins:
enabled: ["ask"]
disabled: []
llm:
provider: "ollama"
host: "localhost"
port: 11434
model: "llama3.1"
timeout_seconds: 60Plugins are compiled into the single binary, then enabled/disabled via config.
Plugin interface:
ID() stringDefaultEnabled() boolDependsOn() []stringConfigSchema() []stringRegister(k *kernel.Kernel) ([]*cobra.Command, error)
Schema keys must be prefixed with the plugin ID (e.g., ask.default_prompt). To allow any nested keys, use a wildcard suffix like ask.settings.*.
ask: ask a model via a provider (Ollama, OpenAI, Mistral)chat: chat with a model (in-memory history)cache: cache inspection and managementtool: run external tools with approvalinvestigate: operator-style investigation with tool executionroles: role loader and auto-role resolvermempalace: optional MCP memory integration
gaia plugins list
gaia plugins enable ask
gaia config list
gaia config get ask.default_prompt
gaia config set ask.default_prompt "Hello"
gaia ask "Ping"
gaia chat
gaia cache list
gaia tool run git status
gaia version
gaia investigate "why is disk full?"
gaia roles list
gaia mem status
gaia mem search "auth decision"
gaia mem inject "auth decision"
gaia ask --role code "Explain this function"
gaia chat --role default
gaia investigate --role operator "analyze CI failures"
gaia tool git commit
gaia ask --pull "Pull model if needed"
gaia chat --pull
gaia investigate --pull "force refresh the model"
gaia config create
gaia config path
gaia config trust .Global flags:
--debugenables debug output across features (including roles debug).
When stdout is a TTY, ask and chat show the model reply in an alternate-screen Bubble Tea panel (same rounded style as cached answers) while tokens stream in. After the stream finishes, the full answer is printed again with the usual framed Answer / Assistant box so it stays in your scrollback. When stdout is not a terminal (pipes, redirection), output falls back to plain streaming text.
Ask uses shared llm.* config, with optional ask.* overrides.
Required shared config:
hostportmodeltimeout_seconds(optional, default: 120)
cache.enabled(default: false)cache.dir(optional)cache.ttl_seconds(optional)cache.refresh(default: false, refreshes cache when set with ask/chat flags)
sanitize.enabled(default: false)sanitize.level(none,light,aggressive)sanitize.max_tokens_after(0 = no cap)sanitize.log_stats(default: false)
tools.allow(list of exact allowed commands)tools.allow_patterns(list of allowed patterns, e.g.git *)tools.deny(list of exact denied commands)tools.deny_patterns(list of denied patterns)
Optional ask overrides:
ask.hostask.portask.modelask.timeout_seconds
MemPalace can be used as an optional memory backend via MCP. Gaia uses JSON-RPC over stdin/stdout and starts MemPalace with:
~/.local/pipx/venvs/mempalace/bin/python -m mempalace.mcp_server
Config keys:
mempalace.mcp.command(default:~/.local/pipx/venvs/mempalace/bin/python)mempalace.mcp.args(default:["-m","mempalace.mcp_server"])mempalace.mcp.timeout_seconds(default: 30)mempalace.debug(default: false, enables MCP request logs)mempalace.inject.enabled(default: false)mempalace.inject.max_results(default: 5)mempalace.inject.min_score(default: 0.0)
ask responses are also persisted to MemPalace synchronously via
mempalace_add_drawer in wing=gaia and room=ask.
When using the Ollama provider, Gaia checks if the model exists via the Ollama API.
If the model is missing, it automatically pulls it. Use --pull to force a refresh
even when the model already exists. Pull progress is shown as a progress bar on stderr.
go test -v ./...