Synced from monorepo

Synced from monorepo

Changes:
- Shell: accept target response id on rewind execute
- Shell: stamp response id on chat user message chunks
- Worktree: optional rebuild and stale git registration cleanup in auto-GC
- Worktree: kind-aware auto-GC TTLs and config knobs
- Worktree: macOS process CWD scan and Unix PID liveness for GC guards
- Worktree: automatic throttled GC on startup (Linux age-based; non-Linux dead-only)
- Pager: add `[ui].combine_queued_prompts` to batch queued follow-ups
- Shell: stop overwriting user skills
- Tools: read markdown in `skills/` directories untruncated
- `/usage` shows per-session token and dollar usage in the TUI
- Security: prompt on environment-dumping `ps` variants
- Security: always-safe `kubectl` no longer runs arbitrary kubeconfig credential plugins without permission
- Tools: make scheduler deletion durable
- Shell: add relocation storage primitives
- Shell: give side model calls their own conversation ids
- Fix five workflow-runtime bugs (budget, pause, cancel, reconnect)
- Security: peel `env -S` / `--split-string` operands in the Bash permission gate (managed deny/ask)
- Pager: expose doctor in the TUI
- Security: block unauthorized RCE via abused safe commands
- Pager idle watcher cue: "1 subagent still running" instead of "watching · 1 subagent"
- Security: block `rg --pre` arbitrary code execution in auto-mode
- Voice: diagnose silent-mic failures (macOS permission) and add doctor/terminal-setup Voice section
- App builder deployer: `allow_forking` and `show_built_with_grok`
- Pager: stop stacking duplicate "Worked for" markers on parked turns
- Shell: support `max` as a distinct reasoning effort tier
- Tools: serialize background `/loop` fires on the whole work unit
- Shell: add working-directory relocation state primitives
- Proto: `ClientToolResult` and `ChatConfig` client-side tools
- Shell: model providers
- Chat: select App Builder product on the Build path
- Shell: attach author identity to feedback when the deployment opts in
- Doctor: fix for SSH wrap setup
- Workflow authoring skills: create-workflow and import-claude-workflow docs
- Add read-only grok doctor
- Sandbox: apply Landlock without a controlling TTY
- Pager: recover image paste over grok wrap on headless remotes
- Pager: make actions screen-mode aware
- Shell: resume sessions when the working directory moves
- Pager: centralize terminal diagnostics
- Workspace: gate inline shell file access
- Pager: centralize terminal probes
- Pager: edit minimal prompts in an external editor
- Pager: standardize backgrounding on Ctrl+B
- Shell: recap rides the parent turn's prompt cache
- Tools: add scheduler lifecycle version clock

Source-Revision: 0f4d7c91b8b2b408333f6de1e8a76cb8eaa71899
This commit is contained in:
grokkybara[bot] 2026-07-21 18:10:23 +00:00
commit 3af4d5d398
556 changed files with 56609 additions and 21892 deletions

View file

@ -1,37 +1,33 @@
# Configuration
Grok reads configuration from local config files, environment variables, and
CLI flags. This document covers the common options.
Grok reads settings from config files, environment variables, and CLI flags. This page covers the common options.
---
## Precedence
Configuration is resolved in this order (highest priority first):
Settings resolve highest-priority first:
1. **CLI flags** (e.g., `--yolo`, `--model`, `--sandbox`)
2. **Environment variables** (e.g., `XAI_API_KEY`, `GROK_MEMORY`)
1. **CLI flags** (e.g. `--yolo`, `--model`, `--sandbox`)
2. **Environment variables** (e.g. `XAI_API_KEY`, `GROK_MEMORY`)
3. **config.toml** (`~/.grok/config.toml`)
4. **Managed / requirements config** (local files your org may deploy, e.g.
`managed_config.toml` / `requirements.toml`)
4. **Managed / requirements config** (files your org may deploy, e.g. `managed_config.toml` / `requirements.toml`)
5. **Built-in defaults**
---
## config.toml (Main Configuration)
## config.toml (main configuration)
Location: `~/.grok/config.toml`
Location: `~/.grok/config.toml`. If the file is missing, Grok uses its built-in defaults, so you only need to set the values you want to override.
If the file does not exist, Grok uses built-in defaults. Specify only the values you want to override.
### General Settings
### General settings
```toml
[cli]
auto_update = true # check for updates on launch
[models]
default = "grok-build" # model used for new sessions
default = "grok-build" # model used for new sessions
web_search = "grok-4.20-multi-agent" # model used by the web_search tool
# Defaults applied to every model; a per-model [model.<id>] value always wins.
@ -45,7 +41,7 @@ inference_idle_timeout_secs = 600
stream_tool_calls = true
[ui]
simple_mode = true # readline-style prompt editing (default); false = vim editing in the prompt
simple_mode = true # readline-style prompt editing (default); false = vim editing in the prompt
vim_mode = false # vim-style scrollback navigation keys (default: false)
max_thoughts_width = 120 # max column width for reasoning display
default_selected_permission = "always_allow_all_sessions" # preselected row on the FIRST approval prompt
@ -68,30 +64,28 @@ screen_mode = "fullscreen" # default render mode: "fullscreen" | "mi
telemetry = false # anonymous usage telemetry
feedback = true # feedback system (default: true)
lsp_tools = false # expose the lsp tool
codebase_indexing = true # code graph indexing
codebase_indexing = true # code graph indexing (default: true)
two_pass_compaction = false # prefire two-pass compaction (default: false, opt-in)
remote_fetch = true # allow optional online model-catalog fetches (default: true;
# set false for firewalled/air-gapped deployments; background
# managed-config sync has its own switch: managed_config)
[session]
auto_compact_threshold_percent = 85 # auto-compact at this % of context window
auto_compact_threshold_percent = 85 # auto-compact at this % of context window (default: 85)
load_envrc = true # load .envrc environment variables
[tools]
respect_gitignore = false # default: false; set true to make every tool skip gitignored files
```
#### Input Mode
#### Input mode
The `simple_mode` setting under `[ui]` controls how you edit text in the
**prompt** — the input editor. It does not change how you navigate the
scrollback; that is governed separately by [`vim_mode`](#vim-mode).
`[ui] simple_mode` controls how you edit text in the **prompt** — the input editor. It has nothing to do with how you move around the scrollback; that's [`vim_mode`](#vim-mode).
| Value | Behavior |
|-------|----------|
| `true` (default) | **Readline editing.** The prompt uses plain readline-style text entry. |
| `false` | **Vim editing (experimental).** The prompt uses vim-style modal editing (normal and insert modes). When the prompt is empty, it starts in normal mode with focus on the scrollback. |
| `true` (default) | **Readline editing.** Plain readline-style text entry. |
| `false` | **Vim editing (experimental).** Vim-style modal editing (normal and insert modes). When the prompt is empty it starts in normal mode with focus on the scrollback. |
To switch the prompt to vim-style editing:
@ -100,20 +94,11 @@ To switch the prompt to vim-style editing:
simple_mode = false
```
You can also toggle this setting from the settings pane (`/settings`
**Disable vim input mode**); Grok writes your choice to `[ui] simple_mode` in
`config.toml`.
You can also flip it from the settings pane (`/settings`**Disable vim input mode**); Grok writes your choice to `[ui] simple_mode`. `simple_mode` and `vim_mode` are independent — one governs the prompt editor, the other governs scrollback navigation. See [Keyboard Shortcuts](03-keyboard-shortcuts.md) for the full binding reference.
`simple_mode` and `vim_mode` are independent: `simple_mode` changes the prompt
editor, and `vim_mode` changes scrollback navigation. See [Keyboard Shortcuts](03-keyboard-shortcuts.md)
for the full binding reference.
#### Default selected permission
#### Default Selected Permission
When the agent asks for permission to run a command (or other tool action),
the approval menu highlights one row by default — the cursor row. The
`default_selected_permission` setting under `[ui]` controls which row that
is on the **first** prompt of a session.
When the agent asks to run a command (or take some other tool action), the approval menu highlights one row by default. `[ui] default_selected_permission` sets which row that is on the **first** prompt of a session.
| Value | Preselected row |
|-------|-----------------|
@ -127,59 +112,30 @@ is on the **first** prompt of a session.
default_selected_permission = "allow_once"
```
After you answer the first prompt, the cursor becomes **sticky**: each later
prompt preselects the same kind of choice you last confirmed (e.g. once you
pick "No", subsequent prompts start on their reject row), carrying across edit
/ bash / MCP prompts until you restart. So `default_selected_permission` only
sets the starting point.
After you answer the first prompt the cursor turns **sticky**: each later prompt preselects whatever you last confirmed (pick "No" once and subsequent prompts start on their reject row), carrying across edit / bash / MCP prompts until you restart. So this setting only picks the starting point.
The accepted values are `always_allow_all_sessions`, `allow_command_always`,
`allow_once`, and `reject` (matching case-insensitively). When the key is unset
— or set to any unrecognized value — it falls back to `always_allow_all_sessions`.
The `allow_command_always` row is scoped to the specific action being approved
(command / tool / domain / edit-session), never a global allow-everything —
that is `always_allow_all_sessions`. Note that the per-command "Always allow"
rows appear only when `[ui] remember_tool_approvals = true` (default: false).
See [22-permissions-and-safety.md](22-permissions-and-safety.md).
Values match case-insensitively; an unset or unrecognized value falls back to `always_allow_all_sessions`. The `allow_command_always` row is always scoped to the specific action being approved (command / tool / domain / edit-session), never a global allow-everything — that's what `always_allow_all_sessions` is for. Note the per-command "Always allow" rows only appear when `[ui] remember_tool_approvals = true` (default false). See [22-permissions-and-safety.md](22-permissions-and-safety.md).
The setting can also be overridden with the `GROK_DEFAULT_SELECTED_PERMISSION`
environment variable — handy for headless / agent test runs that shouldn't
mutate `config.toml`. Precedence: env var → `config.toml`
`always_allow_all_sessions` (the default).
You can also override this with `GROK_DEFAULT_SELECTED_PERMISSION`, which is handy for headless or agent test runs that shouldn't mutate `config.toml`. Precedence: env var → `config.toml``always_allow_all_sessions`.
#### Vim Mode
#### Vim mode
The `vim_mode` setting under `[ui]` controls whether vim-style bindings are
active in the **scrollback** pane. It does not affect the input prompt.
`[ui] vim_mode` controls whether vim-style bindings are active in the **scrollback** pane. It does not affect the prompt.
| Value | Behavior |
|-------|----------|
| `false` (default) | Bare-letter and `Shift+letter` keys (`j`/`k`, `h`/`l`, `g`/`G`, `y`/`Y`, `o`/`O`, `r`, `x`, `e`/`E`, `H`/`L`, plus `i`) are suppressed in the scrollback. Pressing one of those letters focuses the prompt and types the character. Arrows, `Tab`, `Space`, `PageUp`/`PageDown`, and all `Ctrl+letter` shortcuts still navigate the scrollback. `Esc` is **not** a scrollback navigation key — it follows clear / rewind / mid-turn-swallow policy (see [Keyboard Shortcuts](03-keyboard-shortcuts.md#escape)). |
| `false` (default) | Bare-letter and `Shift+letter` keys (`j`/`k`, `h`/`l`, `g`/`G`, `y`/`Y`, `o`/`O`, `r`, `x`, `e`/`E`, `H`/`L`, plus `i`) are suppressed in the scrollback: pressing one focuses the prompt and types the character. Arrows, `Tab`, `Space`, `PageUp`/`PageDown`, and every `Ctrl+letter` shortcut still navigate. `Esc` is **not** a scrollback key — it follows clear / rewind / mid-turn-swallow policy (see [Keyboard Shortcuts](03-keyboard-shortcuts.md#escape)). |
| `true` | All vim-style scrollback bindings are active, exactly as listed in [Keyboard Shortcuts](03-keyboard-shortcuts.md). |
Toggle `vim_mode` at runtime with `/vim-mode`, or from the settings pane
(`/settings`**Vim scrollback navigation**). Grok writes the change to
`[ui] vim_mode` in `~/.grok/config.toml` immediately and applies it to every
future pager session — including new agents and subagents started in the same
process. There is no separate per-session override; whatever is in
`config.toml` is the source of truth on next launch.
Toggle it at runtime with `/vim-mode`, or from `/settings`**Vim scrollback navigation**. Grok writes the change to `[ui] vim_mode` immediately and applies it to every future pager session, including new agents and subagents in the same process. There's no per-session override — `config.toml` is the source of truth on next launch. `vim_mode` is independent of `simple_mode`.
`vim_mode` is independent of `simple_mode`: `vim_mode` controls scrollback
navigation, while `simple_mode` controls editing in the prompt.
#### Screen mode
#### Screen Mode
The `screen_mode` setting under `[ui]` is the **default render mode** for plain
`grok` launches. Configure it from `/settings` → **Default screen mode**
(restart required), or edit `config.toml` by hand. Both choices write
`config.toml`. CLI flags (`--minimal` / `--fullscreen`) and slash commands
(`/minimal` / `/fullscreen`) are session-scoped and do **not** write this key —
after a slash switch, the reverse command (`/fullscreen``/minimal`) returns
you for that session only.
`[ui] screen_mode` is the **default render mode** for plain `grok` launches. Set it from `/settings`**Default screen mode** (restart required) or edit `config.toml` by hand — both write the file. CLI flags (`--minimal` / `--fullscreen`) and slash commands (`/minimal` / `/fullscreen`) are session-scoped and do **not** write this key; after a slash switch, the reverse command returns you for that session only.
| Value | Behavior |
|-------|----------|
| unset | Settings shows **Fullscreen**. At startup there is no sticky preference: legacy `pager.toml` `[terminal] minimal` can still force minimal, and terminals that leak mouse reports (JediTerm/Windows) may auto-open minimal until you set an explicit value. Otherwise the alt-screen policy picks fullscreen vs inline. |
| unset | Settings shows **Fullscreen**. There's no sticky preference at startup: legacy `pager.toml` `[terminal] minimal` can still force minimal, and terminals that leak mouse reports (JediTerm/Windows) may auto-open minimal until you set an explicit value. Otherwise the alt-screen policy picks fullscreen vs inline. |
| `"fullscreen"` | Sticky non-minimal. Fullscreen-vs-inline still follows the alt-screen policy (`--no-alt-screen`, `[terminal] alt_screen`, terminal auto-detection). |
| `"minimal"` | Sticky minimal (scrollback-native) mode. |
@ -187,24 +143,17 @@ A CLI flag always wins over the config value for that invocation.
#### Snap prompt to top on send
By default, sending a prompt scrolls it to the top of the viewport so the
response starts on a fresh page. Set `[ui] page_flip_on_send = false` (or
toggle **Snap prompt to top on send** in `/settings` → Appearance) to leave
the scroll position unchanged when you send. Applies on the next send; no
restart.
By default, sending a prompt scrolls it to the top of the viewport so the response starts on a fresh page. Set `[ui] page_flip_on_send = false` (or toggle **Snap prompt to top on send** in `/settings` → Appearance) to leave the scroll position alone when you send. It takes effect on the next send — no restart.
#### Scrolling
Four `[ui]` settings tune mouse-wheel and trackpad scrolling in the
scrollback. All apply immediately (no restart) and are editable from the
settings pane (`/settings`**Scroll speed** / **Scroll input** /
**Scroll lines** / **Invert scroll**).
Four `[ui]` settings tune mouse-wheel and trackpad scrolling. All apply immediately and are editable from the settings pane (`/settings`**Scroll speed** / **Scroll input** / **Scroll lines** / **Invert scroll**).
| Key | Values (default) | Behavior |
|-----|------------------|----------|
| `scroll_speed` | `1``100` (`50`) | Speed multiplier for both wheel and trackpad. `50` = 1.0x, `1` = 0.1x, `100` = 6.0x. |
| `scroll_mode` | `auto` \| `wheel` \| `trackpad` (`auto`) | Wheel-vs-trackpad detection is heuristic (terminal scroll events carry no magnitude); force one kind when auto-detection misreads your device — e.g. a wheel notch that jumps too far, or a trackpad that feels stepped. |
| `scroll_lines` | `1``10` (unset) | Lines per scroll tick, applied to **both** wheel and trackpad. While unset, each terminal's own profile applies (e.g. a conservative 1 line/event under tmux). Committing any value — even `3`, the number the settings pane displays — switches permanently to that explicit override. |
| `scroll_speed` | `1``100` (`50`) | Speed multiplier for wheel and trackpad. `50` = 1.0x, `1` = 0.1x, `100` = 6.0x. |
| `scroll_mode` | `auto` \| `wheel` \| `trackpad` (`auto`) | Wheel-vs-trackpad detection is heuristic (terminal scroll events carry no magnitude); force one when auto-detection misreads your device — e.g. a wheel notch that jumps too far, or a trackpad that feels stepped. |
| `scroll_lines` | `1``10` (unset) | Lines per scroll tick, applied to **both** wheel and trackpad. While unset, each terminal's own profile applies (e.g. a conservative 1 line/event under tmux). Committing any value — even `3`, the number the settings pane shows — switches permanently to that explicit override. |
| `invert_scroll` | `false` \| `true` (`false`) | Reverse vertical scroll direction ("natural" scrolling). |
```toml
@ -216,14 +165,9 @@ invert_scroll = false
# scroll_lines = 3
```
Each setting also has an environment-variable override, applied on first load
only — handy for headless / test runs that shouldn't mutate `config.toml`:
`GROK_SCROLL_SPEED`, `GROK_SCROLL_MODE`, `GROK_INVERT_SCROLL`
(`1`/`true`/`0`/`false`), and `GROK_SCROLL_LINES`. Precedence: env var →
`config.toml` → default. Unrecognized values fall back to the default, and
out-of-range numbers clamp to the allowed range.
Each setting also has an environment-variable override, applied on first load only (again, handy for headless / test runs): `GROK_SCROLL_SPEED`, `GROK_SCROLL_MODE`, `GROK_INVERT_SCROLL` (`1`/`true`/`0`/`false`), and `GROK_SCROLL_LINES`. Precedence: env var → `config.toml` → default. Unrecognized values fall back to the default, and out-of-range numbers clamp.
### Tool Configuration
### Tool configuration
```toml
[toolset.bash]
@ -236,28 +180,17 @@ timeout_secs = 1800 # seconds to wait when enabled (default:
[toolset.web_fetch]
proxy_endpoint = "https://proxy.example.com" # egress proxy URL
allowed_domains = ["docs.rs", "x.ai"] # override the built-in allowlist
allow_local = false # true = allow localhost / 127.0.0.0/8 / ::1 only
allowed_domains = ["docs.rs", "x.ai"] # override the built-in allowlist
allow_local = false # true = allow localhost / 127.0.0.0/8 / ::1 only
```
`allow_local` is off by default (SSRF fail-closed). When `true` (or
`GROK_WEB_FETCH_ALLOW_LOCAL=1`), `web_fetch` may reach **explicit** loopback
hosts only — private, link-local, and cloud-metadata ranges stay blocked.
Resolution: TOML > env > default off.
`allow_local` is off by default (SSRF fail-closed). Turn it on (or set `GROK_WEB_FETCH_ALLOW_LOCAL=1`) and `web_fetch` may reach **explicit** loopback hosts only — private, link-local, and cloud-metadata ranges stay blocked. Resolution: TOML > env > default off.
`[toolset.ask_user_question]` is honored across **requirements.toml**, **managed
config**, and **user `config.toml`**. Precedence: requirements → env
(`GROK_ASK_USER_QUESTION_TIMEOUT_ENABLED` /
`GROK_ASK_USER_QUESTION_TIMEOUT_SECS`) → user config → managed →
defaults. Set `timeout_enabled = false` in your user config to disable the
automatic questionnaire timeout for yourself; `timeout_secs` must be a
positive integer. `timeout_enabled` can also be toggled from the settings
pane (`/settings`**Ask-Question timeout**, under Agent & Approval);
changes apply to newly started sessions.
`[toolset.ask_user_question]` is honored across **requirements.toml**, **managed config**, and your user **`config.toml`**. Precedence: requirements → env (`GROK_ASK_USER_QUESTION_TIMEOUT_ENABLED` / `GROK_ASK_USER_QUESTION_TIMEOUT_SECS`) → user config → managed → defaults. Set `timeout_enabled = false` in your user config to disable the automatic questionnaire timeout for yourself; `timeout_secs` must be a positive integer. You can also toggle `timeout_enabled` from `/settings`**Ask-Question timeout** (under Agent & Approval); changes apply to newly started sessions.
### Authentication
See [Authentication](02-authentication.md) for full details.
See [Authentication](02-authentication.md) for the full story.
```toml
[auth]
@ -272,7 +205,7 @@ client_id = "0oa1b2c3d4e5f6g7h8i9"
# audience = "https://api.acme.com"
```
### Custom Models
### Custom models
Add custom model endpoints to use alternative providers or self-hosted models.
@ -281,7 +214,7 @@ Add custom model endpoints to use alternative providers or self-hosted models.
model = "model-id" # model identifier sent to API
base_url = "https://api.example.com/v1" # OpenAI-compatible endpoint
name = "Display Name" # shown in model picker
description = "Model description" # optional
description = "Model description" # optional
api_key = "sk-..." # API key for this provider
env_key = "XAI_API_KEY" # env var(s) holding the API key; string or array (first set, non-empty wins)
temperature = 0.7 # sampling temperature (0.0-2.0)
@ -292,16 +225,16 @@ context_window = 128000 # context window size (for auto-compact)
Credential resolution: `api_key` > `env_key` > signed-in session token > `XAI_API_KEY`.
Override built-in models by using their name as the section key:
To override a built-in model, use its name as the section key and set only the fields you need:
```toml
[model.grok-build]
api_key = "my-api-key" # only override the fields you need
api_key = "my-api-key"
```
### MCP Servers
### MCP servers
Configure external tool integrations via the Model Context Protocol.
Configure external tool integrations over the Model Context Protocol.
```toml
[mcp_servers.github]
@ -310,7 +243,7 @@ args = ["-y", "@modelcontextprotocol/server-github"]
env = { GITHUB_PERSONAL_ACCESS_TOKEN = "ghp_xxx" }
enabled = true # enable/disable (default: true)
startup_timeout_sec = 30 # init timeout in seconds (default: 30)
tool_timeout_sec = 6000 # tool call timeout in seconds (default: 6000)
tool_timeout_sec = 6000 # tool call timeout in seconds (default: 6000)
tool_timeouts = { create_issue = 120 } # per-tool timeout overrides
[mcp_servers.postgres]
@ -322,9 +255,9 @@ url = "https://mcp.example.com/api/mcp" # HTTP/SSE transport
headers = { "x-mcp-session-id" = "{{session_id}}" }
```
MCP servers can also be configured per-project in `.grok/config.toml`. Project-scoped config contributes `[mcp_servers]`, `[plugins]`, and `[permission]` rules; other sections load only from `~/.grok/config.toml`.
MCP servers can also be set per-project in `.grok/config.toml`. Project-scoped config contributes `[mcp_servers]`, `[plugins]`, and `[permission]` rules; every other section loads only from `~/.grok/config.toml`.
Priority for `[mcp_servers]` and `[plugins]`: `.grok/config.toml` (current dir) > `<repo-root>/.grok/config.toml` > `~/.grok/config.toml`. `[permission]` rules are not overridden by priority; they merge across all files with `deny` > `ask` > `allow` (see [22-permissions-and-safety.md](22-permissions-and-safety.md)).
Priority for `[mcp_servers]` and `[plugins]`: `.grok/config.toml` (current dir) > `<repo-root>/.grok/config.toml` > `~/.grok/config.toml`. `[permission]` rules aren't overridden by priority — they merge across all files with `deny` > `ask` > `allow` (see [22-permissions-and-safety.md](22-permissions-and-safety.md)).
### Memory
@ -369,6 +302,21 @@ explore = "grok-build" # route to different models
To pin the model a subagent uses, set its entry under `[subagents.models]`.
### Goal mode and background workflows
`/goal` has two drivers, chosen by the background-workflows setting. With workflows enabled, the host-owned workflow engine evaluates rounds and drives completion verification; with them disabled, `/goal` falls back to the legacy model-facing `update_goal` tool. Whether `/goal` is available at all is a separate switch (the goal feature setting).
Background workflows — the `workflow` tool, named `.grok/workflows/*.rhai` scripts, `/deep-research`, and `/workflow` launches — are **off by default**.
```toml
[workflows]
enabled = true # enable background workflows (or GROK_WORKFLOWS=1)
```
Project workflows are discovered from `<repo-root>/.grok/workflows/`; user workflows from `~/.grok/workflows/`. Discovery and invocation key off the script's `meta.name`, so keep each filename aligned with its `meta.name`. Built-ins win over project names, and project names win over user names, so keep names unique across scopes.
Each launch gets a session-unique display handle such as `deep-research-2`. That handle is what you see in the `/workflows` run dashboard and pass to `/workflow pause`, `resume`, or `stop` — the internal run IDs never surface in commands. A numbered handle isn't a reusable definition name, so the dashboard disables **save** until you pick a new unique `meta.name` and save the edited script yourself. See [Slash Commands](04-slash-commands.md) for examples.
### Skills
```toml
@ -378,11 +326,9 @@ ignore = ["~/my-team-skills/wip"] # paths to exclude
disabled = ["wip-skill"] # skill names to keep listed but inactive
```
### Harness Compatibility
### Harness compatibility
Control vendor compatibility for Cursor, Claude, and Codex. Every cell defaults to `true`; session cells remain staged/inert until the foreign-session scanner consumes them.
Session cells remain staged until a foreign-session scanner consumes them. Each tool requires both its `sessions` cell and corresponding `resume-claude`, `resume-codex`, or `resume-cursor` skill; a missing skill means zero foreign-session filesystem I/O.
Control vendor compatibility for Cursor, Claude, and Codex. Every cell defaults to `true`. Session cells stay staged and inert until a foreign-session scanner consumes them, and each tool needs both its `sessions` cell and the matching `resume-claude`, `resume-codex`, or `resume-cursor` skill — a missing skill means zero foreign-session filesystem I/O.
```toml
[compat.cursor]
@ -405,19 +351,13 @@ sessions = true # staged; no scanner consumer yet
sessions = true # staged; no scanner consumer yet
```
Codex `skills`, `rules`, `agents`, `mcps`, and `hooks` cells are reserved and currently inert; they do not enable `.codex` discovery.
Codex's `skills`, `rules`, `agents`, `mcps`, and `hooks` cells are reserved and currently inert they do not enable `.codex` discovery.
For Claude and Cursor, `rules` and `agents` are independent: disabling named instruction files does not disable either the home or project rules directory, and disabling rules does not disable named files. Claude's `agents` cell gates home-level `~/.claude/` named files and project `<dir>/.claude/CLAUDE*.md`; generic top-level `Claude.md`, `CLAUDE.md`, and `CLAUDE.local.md` remain recognized. Project rule paths are scanned at every directory from the repo root to the current directory.
For Claude and Cursor, `rules` and `agents` are independent: turning off named instruction files doesn't disable the home or project rules directory, and turning off rules doesn't disable named files. Claude's `agents` cell gates home-level `~/.claude/` named files and project `<dir>/.claude/CLAUDE*.md`; generic top-level `Claude.md`, `CLAUDE.md`, and `CLAUDE.local.md` stay recognized. Project rule paths are scanned at every directory from the repo root down to the current one.
Each cell can be toggled via environment variable or `config.toml`. See the
environment-variables reference for the env var names. Resolution order:
env var > config.toml > default (on).
Each cell can be set via environment variable or `config.toml`; see the environment-variables reference for the names. Resolution: env var > config.toml > default (on).
`grok inspect` reports cells that still need session-start resolution as
`?` until a value is available; cells with an explicit env or TOML value
use that value. Affected discovery entries report
`compatibilityStatus: "unresolved"` in JSON and `[compat unresolved]` in
human output.
`grok inspect` reports cells that still need session-start resolution as `?` until a value is available; cells with an explicit env or TOML value use that value. Affected discovery entries report `compatibilityStatus: "unresolved"` in JSON and `[compat unresolved]` in human output.
### Plugins
@ -429,9 +369,9 @@ disabled = ["user/a1b2c3d4/noisy-plugin"]
### Hints
The `[hints]` table holds small persisted UI preferences — mostly "stop asking me" opt-outs. Grok writes these for you when you pick a "don't ask again" / "reset in config.toml" option in the TUI, but you can edit or remove them by hand. Deleting a key restores the default behavior.
`[hints]` holds small persisted UI preferences — mostly "stop asking me" opt-outs. Grok writes these for you when you pick a "don't ask again" option in the TUI, but you can edit or delete them by hand; removing a key restores the default.
`[hints]` is read from the **effective config merge** (same precedence as other settings): system managed → user `managed_config.toml` → user `config.toml` → user `requirements.toml` → system `requirements.toml`. Higher-priority layers override lower ones. The TUI only **writes** opt-outs to user `~/.grok/config.toml`.
`[hints]` is read from the **effective config merge**, with the usual precedence: system managed → user `managed_config.toml` → user `config.toml` → user `requirements.toml` → system `requirements.toml`, higher layers winning. The TUI only ever **writes** opt-outs to your user `~/.grok/config.toml`.
```toml
[hints]
@ -443,17 +383,14 @@ fork_worktree_mode = "ask" # /fork worktree prompt: "ask" | "always"
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `project_picker_disabled` | bool | `false` | When `true`, skips the picker that asks you to choose a project directory on the first prompt when Grok is launched from a non-project directory (home, Desktop, Downloads, `/tmp`). Set automatically when you choose **"Don't ask me again"** in that picker. Teams can pin this in `managed_config.toml` or `requirements.toml` via `[hints] project_picker_disabled = true`. |
| `project_picker_disabled` | bool | `false` | When `true`, skips the picker that asks you to choose a project directory on the first prompt when Grok launches from a non-project directory (home, Desktop, Downloads, `/tmp`). Set automatically when you choose **"Don't ask me again"** in that picker. Teams can pin it in `managed_config.toml` or `requirements.toml`. |
| `memory_modal_fullscreen` | bool | `false` | Remembers whether the memory modal was last opened fullscreen. |
| `new_session_worktree_mode` | string | `"never"` | Worktree prompt for `/new`: `ask` shows the popup, `always` creates a worktree, `never` skips it. |
| `fork_worktree_mode` | string | `"ask"` | Worktree prompt for `/fork`: `ask`, `always`, or `never`. |
### Notifications
Send terminal notifications when the agent finishes a turn or needs
approval. Notifications use terminal-native protocols (OSC 9, OSC 99, OSC 777,
or BEL) and are focus-gated by default so they only fire when you are not
looking at the terminal.
Fire terminal notifications when the agent finishes a turn or needs approval. They use terminal-native protocols (OSC 9, OSC 99, OSC 777, or BEL) and are focus-gated by default, so they only fire when you're not looking at the terminal.
```toml
[ui.notifications]
@ -472,15 +409,15 @@ items = ["action-required", "spinner", "activity", "session-name", "grok"]
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `method` | string | `"auto"` | Notification protocol. `auto` picks the best for your terminal. |
| `condition` | string | `"unfocused"` | When to notify: `unfocused` (only when terminal lost focus), `always`, or `never`. |
| `idle_threshold_secs` | integer | `3` | Minimum seconds the terminal must be unfocused before a notification fires. |
| `condition` | string | `"unfocused"` | When to notify: `unfocused` (only when the terminal lost focus), `always`, or `never`. |
| `idle_threshold_secs` | integer | `3` | Minimum seconds unfocused before a notification fires. |
| `events` | array | `["turn_complete", "approval_required"]` | Events that trigger notifications. Options: `turn_complete`, `approval_required`, `session_ready`, `task_complete`, `agent_error`. |
| `sleep_prevention` | bool | `true` | Keep the display awake while the agent is working (macOS/Linux). |
| `sleep_prevention` | bool | `true` | Keep the display awake while the agent works (macOS/Linux). |
| `progress_bar` | bool | `true` | Show a progress indicator in the terminal tab (OSC 9;4). |
| `title.enabled` | bool | `true` | Set the terminal title to reflect agent state. |
| `title.items` | array | (see above) | Items shown in the title bar. Options: `action-required`, `spinner`, `activity`, `session-name`, `cwd`, `model`, `turn-timer`, `grok`. |
#### Terminal Support Matrix
#### Terminal support matrix
| Terminal | Auto Protocol | Focus Tracking | Progress Bar |
|----------|---------------|----------------|--------------|
@ -496,13 +433,11 @@ items = ["action-required", "spinner", "activity", "session-name", "grok"]
| Grok Desktop | None (native) | N/A | N/A |
| Unknown | BEL | No | No |
When `method = "auto"`, Grok detects the terminal brand and selects the best
protocol automatically. Set `method` explicitly to override auto-detection.
With `method = "auto"`, Grok detects the terminal brand and picks the best protocol. Set `method` explicitly to override that.
#### Notification Hooks
#### Notification hooks
Run custom commands when events occur. Hooks receive environment variables
`$GROK_EVENT`, `$GROK_MESSAGE`, and `$GROK_SESSION_ID`.
Run your own commands when events fire. Hooks receive `$GROK_EVENT`, `$GROK_MESSAGE`, and `$GROK_SESSION_ID` in the environment.
```toml
# macOS native notification
@ -532,48 +467,37 @@ timeout_secs = 5
| `command` | string | (required) | Shell command to run. |
| `events` | array | `[]` | Events that trigger this hook (empty = all events). |
| `only_unfocused` | bool | `true` | Only fire when the terminal has lost focus. |
| `timeout_secs` | integer | `10` | Kill the hook process after this many seconds (default: 10). |
| `timeout_secs` | integer | `10` | Kill the hook process after this many seconds. |
#### Troubleshooting
**Notifications not working in tmux:**
tmux blocks escape sequences by default. Enable passthrough for your terminal:
**Notifications not working in tmux:** tmux blocks escape sequences by default, so enable passthrough:
```bash
# In ~/.tmux.conf
set -g allow-passthrough on
```
Then restart tmux. If passthrough is not available (tmux < 3.3), set
`method` explicitly to `"bel"` which works without passthrough.
Restart tmux afterward. If passthrough isn't available (tmux < 3.3), set `method = "bel"`, which works without it.
**Focus tracking not working:**
Some terminals do not report focus events. If `condition = "unfocused"` never
fires, try `condition = "always"` as a fallback. Grok supports focus tracking
in every detected terminal except Apple Terminal and unrecognized terminals.
**Focus tracking not working:** some terminals don't report focus events. If `condition = "unfocused"` never fires, try `condition = "always"`. Grok supports focus tracking in every detected terminal except Apple Terminal and unrecognized ones.
**Sleep prevention not taking effect:**
On macOS, sleep prevention uses `IOPMAssertionCreateWithName` via CoreFoundation.
On Linux, it uses `systemd-inhibit` (must be on `$PATH`). Check that the
relevant tool is available. Sleep prevention is only active during agent turns
and releases automatically when the turn ends.
**Sleep prevention not taking effect:** on macOS, sleep prevention uses `IOPMAssertionCreateWithName` via CoreFoundation; on Linux, `systemd-inhibit` (which must be on `$PATH`). Make sure the relevant tool is available. Prevention is only active during agent turns and releases automatically when the turn ends.
### Keyboard Shortcuts
### Keyboard shortcuts
Keyboard shortcuts are **not configurable** via config files. All bindings are built in.
See [Keyboard Shortcuts](03-keyboard-shortcuts.md) for the complete reference.
Keyboard shortcuts are **not** configurable — all bindings are built in. See [Keyboard Shortcuts](03-keyboard-shortcuts.md) for the complete reference.
### Telemetry
Independent knobs (see [Monitoring Usage](24-monitoring-usage.md#related-settings)):
These are independent knobs (see [Monitoring Usage](24-monitoring-usage.md#related-settings)):
- **`[features] telemetry`** / `GROK_TELEMETRY_ENABLED`: product analytics master switch. `/privacy` does not change it.
- **`/privacy`** / Settings: coding data sharing (separate from telemetry).
- **`[telemetry] trace_upload`** / `GROK_TELEMETRY_TRACE_UPLOAD`: session traces; follows telemetry when unset.
- **`[telemetry] otel_*`** / `GROK_EXTERNAL_OTEL`: external OTEL to your collector (below).
- **`[features] telemetry`** / `GROK_TELEMETRY_ENABLED` — the product-analytics master switch. `/privacy` doesn't change it.
- **`/privacy`** / Settings — coding-data sharing, separate from telemetry.
- **`[telemetry] trace_upload`** / `GROK_TELEMETRY_TRACE_UPLOAD` session traces; follows telemetry when unset.
- **`[telemetry] otel_*`** / `GROK_EXTERNAL_OTEL` — external OTEL to your own collector (below).
When telemetry is enabled, enterprises that run their own collector can redirect
it or selectively disable parts of it under `[telemetry]`:
When telemetry is on, enterprises running their own collector can redirect it or turn parts off under `[telemetry]`:
```toml
[telemetry]
@ -583,9 +507,9 @@ mixpanel_enabled = false # disable Mixpanel pro
trace_upload = false # disable session/trace uploads (inherits the telemetry toggle when unset)
```
Set these only to point telemetry at your own infrastructure or to turn parts of it off. The built-in endpoint and credentials are managed by Grok; leave them unset to use the defaults.
Set these only to point telemetry at your own infrastructure or to switch parts off. The built-in endpoint and credentials are managed by Grok — leave them unset to use the defaults.
The same `[telemetry]` table also configures the **external OpenTelemetry stream**, an independent opt-in (it does not require the telemetry toggle above) that ships a curated, content-free usage schema to your *own* OTLP collector. Collector auth is supplied via `OTEL_EXPORTER_OTLP_HEADERS` and is never stored on disk. See [Monitoring & Usage](24-monitoring-usage.md) for the full schema, env vars, and privacy model.
The same `[telemetry]` table also configures the **external OpenTelemetry stream**, an independent opt-in (it doesn't require the telemetry toggle above) that ships a curated, content-free usage schema to your *own* OTLP collector. Collector auth comes from `OTEL_EXPORTER_OTLP_HEADERS` and is never stored on disk. See [Monitoring & Usage](24-monitoring-usage.md) for the full schema, env vars, and privacy model.
```toml
[telemetry]
@ -598,7 +522,7 @@ otel_log_user_prompts = false # content gate (admins
otel_log_tool_details = false # content gate (admins can pin via requirements)
```
### Enterprise Deployment
### Enterprise deployment
A complete config for enterprise use:
@ -626,11 +550,9 @@ telemetry = false
---
## pager.toml (Appearance Configuration)
## pager.toml (appearance configuration)
Location: `~/.grok/pager.toml`
Controls the visual appearance and behavior of the TUI. Changes are applied on restart.
Location: `~/.grok/pager.toml`. This controls the TUI's look and feel. Changes apply on restart.
### Terminal
@ -639,9 +561,9 @@ Controls the visual appearance and behavior of the TUI. Changes are applied on r
alt_screen = "auto" # fullscreen mode: "auto", "always", "never"
```
- `auto` (default): Use alternate screen when the terminal supports it
- `always`: Always use alternate screen
- `never`: Run inline in the terminal's main scrollback buffer
- `auto` (default): use the alternate screen when the terminal supports it.
- `always`: always use the alternate screen.
- `never`: run inline in the terminal's main scrollback buffer.
### Animation
@ -660,7 +582,7 @@ mouse_hover = true # show hover highlight on the prompt widge
show_prefix = true # show the prompt prefix character
```
Compact mode is not persisted here. Control it at runtime with `[ui] compact_mode` or the `/compact-mode` command.
Compact mode isn't persisted here — control it at runtime with `[ui] compact_mode` or the `/compact-mode` command.
### Scrollback
@ -699,15 +621,9 @@ highlight_overlays_border = false # highlight extends over selection box bor
dim_accent = 0.5 # dimming factor for collapsed accents (0.0-1.0)
```
`respect_manual_folds` is off by default; set it to `true` to opt in. When
enabled, a block you fold by hand is pinned: streaming updates and finish
events (such as a thinking block ending) leave its fold state alone, and
expanding a block while follow-mode is tailing new content stops the
auto-scroll so the view stays put. Follow resumes via `Shift+G`, `j` at the
last entry, scrolling past the bottom, or sending a new prompt. `Shift+E`
clears all pins; `Ctrl+E` clears pins on thinking blocks.
`respect_manual_folds` is off by default. Turn it on and a block you fold by hand is pinned: streaming updates and finish events (a thinking block ending, say) leave its fold state alone, and expanding a block while follow-mode is tailing new content stops the auto-scroll so the view stays put. Follow resumes via `Shift+G`, `j` at the last entry, scrolling past the bottom, or sending a new prompt. `Shift+E` clears all pins; `Ctrl+E` clears pins on thinking blocks.
### Block Configuration
### Block configuration
```toml
[scrollback.blocks.edit]
@ -737,9 +653,10 @@ badge_format = "default" # "default", "colon", or "comma"
```
Badge format examples:
- `default`: `2/5` -- a `done/total` progress fraction (done = completed, total = all tasks except cancelled)
- `colon`: `[>:1 [ ]:4 ok:3 x:2]` -- icon:count
- `comma`: `[1 >, 4 [ ], 3 ok, 2 x]` -- count icon, comma-separated
- `default`: `2/5` — a `done/total` progress fraction (done = completed, total = all tasks except cancelled).
- `colon`: `[>:1 [ ]:4 ok:3 x:2]` — icon:count.
- `comma`: `[1 >, 4 [ ], 3 ok, 2 x]` — count icon, comma-separated.
### Plugins
@ -749,9 +666,9 @@ disable_plugins = false # hide hooks/plugins UI entirely
---
## Environment Variables
## Environment variables
Key environment variables. See the README for the complete list.
The key ones. See the README for the complete list.
### Authentication
@ -777,8 +694,9 @@ Key environment variables. See the README for the complete list.
|----------|-------------|
| `GROK_MEMORY` | Enable (`1`) or disable (`0`) cross-session memory |
| `GROK_SUBAGENTS` | Enable (`1`) or disable (`0`) subagents |
| `GROK_WORKFLOWS` | Enable (`1`) or disable (`0`) background workflows and select the `/goal` driver (default off: legacy `update_goal`; on: host-owned workflow driver) |
| `GROK_WEB_FETCH` | Enable (`1`) or disable (`0`) the web_fetch tool |
| `GROK_WEB_FETCH_ALLOW_LOCAL` | Allow `web_fetch` to explicit loopback hosts only (`localhost` / `127.0.0.0/8` / `::1`). Same as `[toolset.web_fetch] allow_local`. Default off. Private/metadata stay blocked. |
| `GROK_WEB_FETCH_ALLOW_LOCAL` | Allow `web_fetch` to explicit loopback hosts only (`localhost` / `127.0.0.0/8` / `::1`). Same as `[toolset.web_fetch] allow_local`. Default off; private/metadata stay blocked. |
| `GROK_AGENT` | Custom agent definition path or name |
| `GROK_SANDBOX` | Sandbox profile (off, workspace, devbox, read-only, strict; or a custom profile name) |
@ -786,8 +704,8 @@ Key environment variables. See the README for the complete list.
| Variable | Description |
|----------|-------------|
| `GROK_LOG_FILE` | Write logs to this file path (the value is used verbatim as the path) |
| `RUST_LOG` | Log level filter (for example `debug`); controls the `GROK_LOG_FILE` log and headless stderr output |
| `GROK_LOG_FILE` | Write logs to this file path (used verbatim as the path) |
| `RUST_LOG` | Log level filter (e.g. `debug`); controls the `GROK_LOG_FILE` log and headless stderr output |
### Paths
@ -809,7 +727,7 @@ Key environment variables. See the README for the complete list.
---
## File Locations
## File locations
| Path | Description |
|------|-------------|
@ -822,7 +740,7 @@ Key environment variables. See the README for the complete list.
| `~/.grok/plugins/` | User-scoped plugins |
| `~/.grok/agents/` | User-scoped agent definitions |
| `~/.grok/lsp.json` | LSP server configuration (user-scoped) |
| `~/.grok/logs/` | Internal log files (for example `unified.jsonl`, MCP server logs) |
| `~/.grok/logs/` | Internal log files (e.g. `unified.jsonl`, MCP server logs) |
| `.grok/config.toml` | Project-scoped MCP servers, plugins, and permission rules |
| `.grok/skills/` | Project-scoped skill definitions |
| `.grok/plugins/` | Project-scoped plugins |
@ -832,9 +750,9 @@ Key environment variables. See the README for the complete list.
---
## Project-Scoped Configuration
## Project-scoped configuration
Some configuration can be set per-project by placing files in `.grok/` within your repository:
Some settings can be set per-project by placing files in `.grok/` inside your repository:
| File | What it configures |
|------|--------------------|
@ -846,13 +764,13 @@ Some configuration can be set per-project by placing files in `.grok/` within yo
| `.grok/sandbox.toml` | Custom sandbox profiles |
| `AGENTS.md` | Project instructions (system prompt) |
Project-scoped MCP servers override global ones with the same name (full replacement, not merge).
Project-scoped MCP servers override global ones with the same name (full replacement, not a merge).
---
## LSP Servers
## LSP servers
Language servers power passive diagnostics and the optional `lsp` tool (see the [`lsp_tools`](#general-settings) feature flag). Server definitions are collected from three sources and merged by server name:
Language servers power passive diagnostics and the optional `lsp` tool (see the [`lsp_tools`](#general-settings) feature flag). Definitions come from three sources and merge by server name:
| Source | Location | Scope |
|--------|----------|-------|
@ -860,10 +778,10 @@ Language servers power passive diagnostics and the optional `lsp` tool (see the
| Project | `.grok/lsp.json` | Current repository |
| Plugin | A trusted plugin's `.lsp.json` file, or an inline `lspServers` block in its `plugin.json` | Wherever the plugin is enabled |
When the same server name is defined by more than one source, it is resolved in this order (highest priority first):
When the same server name comes from more than one source, it resolves highest-priority first:
1. **Project** -- `.grok/lsp.json`
2. **User** -- `~/.grok/lsp.json`
3. **Plugins** -- file-based `.lsp.json`, then inline `lspServers`, in plugin load order
1. **Project** `.grok/lsp.json`
2. **User** `~/.grok/lsp.json`
3. **Plugins** file-based `.lsp.json`, then inline `lspServers`, in plugin load order
Project and user entries replace lower-priority ones with the same name. Plugin entries only add servers whose names are not already defined by a local file, so a local `lsp.json` always wins over a plugin. Plugin LSP servers load only after the plugin is trusted (see [Plugins](09-plugins.md)).
Project and user entries replace lower-priority ones of the same name. Plugin entries only add servers whose names aren't already defined by a local file, so a local `lsp.json` always wins over a plugin. Plugin LSP servers load only after the plugin is trusted (see [Plugins](09-plugins.md)).