Synced from monorepo

Synced from monorepo

Changes:
- Workspace server: report `/ready` as failed with dwell on hub connect failure
- Refresh OIDC token for the Grok agent in the shell
- ACP terminal output recorder
- Cross-platform provider auth commands in the shell
- Default `/resume` to Grok sessions with a hint for hidden external sessions
- Resume sessions by title with `--resume`
- Limit app-builder archive size
- Data-driven tag labels for slash commands
- Doctor fixes for tmux
- Custom provider gateways and subprocess environment policy in the shell
- `/tutorial` — opt-in onboarding tour of Grok Build
- Soft and required CLI version checks in the shell
- Privacy banner env overrides survive live settings updates
- Add remote flag to override the image-edit model
- Return profile fields from auth info even when the access token is expired
- Add edit control on queued prompt rows
- Keep fail-closed policy when clearing orphans with no team
- Setting to disable the Ctrl+Space/F8 voice shortcut
- Pass `--raw` to pw-record so Linux dictation works on older PipeWire
- Validate git URLs when adding marketplace entries
- Stop shipping stale tool-doc parameter and tool names
- Re-point dashboard attach after `/fork` only when the parent was attached
- Surface Grok Computer media-generation results as file-path chunks
- Clear web background-task tray on kill and keep the task description
- Show privacy upsell banner in agent view until acted on
- Add tools-server client callback surface
- Protect persistent global hook sources

Source-Revision: 95d84f443eddcbed6cbfd6eed22e2eafe6b3939d
This commit is contained in:
grokkybara[bot] 2026-07-23 17:12:33 +00:00
commit 69f0ba880a
286 changed files with 22939 additions and 9624 deletions

View file

@ -347,6 +347,16 @@ Browse the in-TUI How-to Guides, open the online Build docs, or jump straight to
- `/docs web` opens https://docs.x.ai/build/overview in your browser.
- `/docs <title>` opens a specific guide by case-insensitive title match.
### `/tutorial`
Open the onboarding tutorial: a short list of topics (your first prompt, attaching context, navigation, slash commands, worktrees, plan mode, customization, switching from another agent tool) — each a ~30-second read, with `→` flowing straight to the next topic. Nothing auto-shows — this command (or the command palette) is the way in.
```
/tutorial
```
Aliases: `/tour`, `/onboarding`
### `/import-claude`
Open the Claude import modal to bring over `~/.claude` settings: permissions, environment variables, MCP servers, hooks, and paths.

View file

@ -221,9 +221,11 @@ temperature = 0.7 # sampling temperature (0.0-2.0)
top_p = 0.95 # nucleus sampling parameter
max_completion_tokens = 8192 # max tokens per response
context_window = 128000 # context window size (for auto-compact)
query_params = { api-version = "2026-07-22" } # query params appended to every request URL
env_http_headers = { "X-Tenant" = "TENANT_TOKEN" } # request headers from env vars, resolved at client build
```
Credential resolution: `api_key` > `env_key` > signed-in session token > `XAI_API_KEY`.
Credential resolution: `api_key` > `env_key` > signed-in session token > `XAI_API_KEY`. See [Custom Models](11-custom-models.md#request-query-parameters) for `query_params` and `env_http_headers`, and [Sandbox Mode](18-sandbox.md#shell-environment-policy) for `[shell_environment_policy]`, which restricts the environment variables tool subprocesses inherit.
To override a built-in model, use its name as the section key and set only the fields you need:
@ -513,6 +515,41 @@ otel_log_user_prompts = false # content gate (admins
otel_log_tool_details = false # content gate (admins can pin via requirements)
```
### Version pinning
Control which versions the CLI may auto-update to and which versions may run. Set
these in `[cli]`, or in a managed layer for fleet-wide policy. Each has an
environment override that can only tighten the bound, for CI and testing.
> **Changed:** `minimum_version` no longer blocks startup. It is now a soft
> anti-downgrade floor for the updater. For a hard floor that prevents old
> versions from starting, use `required_minimum_version`.
```toml
[cli]
minimum_version = "0.2.109" # updater won't downgrade below this
maximum_version = "0.2.180" # updater won't install above this
required_minimum_version = "0.2.100" # refuse to start below this
required_maximum_version = "0.2.200" # refuse to start above this
```
- `minimum_version` (`GROK_MINIMUM_VERSION`) is a soft anti-downgrade floor. The
updater skips a target below it and keeps the current version. It never blocks
startup.
- `maximum_version` (`GROK_MAXIMUM_VERSION`) is a soft ceiling. The updater caps
its target at it and never installs above it.
- `required_minimum_version` (`GROK_REQUIRED_MINIMUM_VERSION`) and
`required_maximum_version` (`GROK_REQUIRED_MAXIMUM_VERSION`) are hard bounds. If
the running version is outside the range, the CLI exits at startup and instructs
the user to install an approved version. `grok update` and `grok --version` keep
working so an out-of-range install can recover.
- Bounds resolve across config layers by tightening only: a floor takes the
highest value and a ceiling the lowest, so a managed bound can't be loosened,
and a user or environment bound can't cancel a managed hard bound. An invalid
value is ignored so a bad policy can't block startup.
- An explicit `grok update --version X` is allowed above the ceiling, to recover
from a too-new install, and rejected below the hard floor.
### Enterprise deployment
A complete config for enterprise use:

View file

@ -87,6 +87,8 @@ top_p = 0.95 # Nucleus sampling parameter
max_completion_tokens = 8192 # Maximum tokens per response
context_window = 128000 # Total context window in tokens
extra_headers = { "x-api-key" = "sk-..." } # Extra request headers, sent verbatim (optional)
query_params = { api-version = "2026-07-22" } # Query params appended to every request URL (optional)
env_http_headers = { "X-Tenant" = "TENANT_TOKEN" } # Headers from env vars, resolved at client build (optional)
```
### Credential Resolution
@ -131,6 +133,36 @@ This is a small, fixed set of environment-wide knobs. Settings that identify a s
> **Note on `stream_tool_calls`:** this one affects request *shape*, not just sampling. A few endpoints (some BYOK providers) expect it left unset; if a global `stream_tool_calls = true` causes problems for such a model, opt that model out with `stream_tool_calls = false` in its `[model.<id>]` block.
### Request Query Parameters
Some gateways route or version on the query string. `query_params` appends percent-encoded query parameters to every request Grok makes for a model. For example, a gateway that selects an API version this way:
```toml
[model.my-gateway]
model = "my-model"
base_url = "https://gateway.example/v1"
api_backend = "responses"
env_key = "GATEWAY_API_KEY"
query_params = { api-version = "2026-07-22" }
```
A key that also appears in the `base_url` query string is overridden (last value wins) rather than duplicated. Query parameters are saved in the session, so do not put secrets in them: use `env_http_headers` for a secret.
### Environment-Variable Headers
`env_http_headers` maps a request header to the name of an environment variable that supplies its value, so a per-request secret never has to be written into `config.toml`:
```toml
[model.gateway]
model = "my-model"
base_url = "https://gateway.example/v1"
env_http_headers = { "X-Tenant-Token" = "GATEWAY_TENANT_TOKEN" }
```
Grok reads each variable when it builds the client for a session and places the value in the request headers only, never on disk. A header is skipped when its variable is unset or blank, and a resolved value overrides an `extra_headers` entry of the same name. Use `extra_headers` for a static value and `env_http_headers` for one that comes from the environment.
Both fields also work on a shared `[model_providers.<id>]` block. A model that points at a provider with `model_provider = "<id>"` inherits the provider's `query_params` and `env_http_headers` when it sets none of its own, matching how `extra_headers` is inherited.
---
## Overriding Built-in Models

View file

@ -24,7 +24,7 @@ Grok processes the prompt, runs any necessary tools, and prints the result to st
| `-m, --model <MODEL>` | Model to use (e.g., `grok-build`) |
| `-s, --session-id <ID>` | Create a **new** session with this **UUID** (errors if invalid UUID or already in use under the target session directory; does not resume — use `-r`/`-c`) |
| `--fork-session` | With `-r`/`-c`, fork into a new session ID instead of appending to the original |
| `-r, --resume <ID>` | Resume an existing session (errors if not found) |
| `-r, --resume <ID_OR_TITLE>` | Resume an existing session by ID, or by title for the current directory, ignoring letter case (a sole manually renamed match wins among duplicates; remaining duplicates error with their IDs; UUID-shaped values always take the ID path; scripts should prefer IDs) |
| `-c, --continue` | Continue the most recent session in current directory |
| `--cwd <PATH>` | Set working directory |
| `--output-format <FMT>` | Output format: `plain`, `json`, `streaming-json` |
@ -256,7 +256,7 @@ grok -p "hello" --session-id "$(uuidgen | tr '[:upper:]' '[:lower:]')" --output-
### Resume (`-r`)
The `-r/--resume` flag resumes a specific session by ID. It errors if the session does not exist:
The `-r/--resume` flag resumes a specific session by ID, or by title for the current directory when the value is not an ID, ignoring letter case (a sole manually renamed match wins among duplicates; remaining duplicates error with their IDs; UUID-shaped values always take the ID path — scripts should prefer IDs). It errors if the session does not exist:
```bash
# Get the session ID from a previous JSON response

View file

@ -82,13 +82,15 @@ To switch between, rename, or close the sessions that are currently active (the
### From the Command Line
Resume a specific session by ID:
Resume a specific session by ID or title:
```bash
grok --resume <session-id>
grok --resume <session-id-or-title>
```
Run `grok --resume` without an ID to resume the most recent session for the current directory.
A value that is not a session ID is matched against session titles for the current directory, ignoring letter case (a simple lowercase comparison) — handy after `/rename`. If several sessions share the title, a single manually renamed session wins over auto-generated duplicates; otherwise the command errors and lists the matching IDs. UUID-shaped values are always treated as session IDs, never titles. Scripts should prefer IDs.
Run `grok --resume` without a value to resume the most recent session for the current directory.
### From the Welcome Screen
@ -187,14 +189,14 @@ In headless mode, you manage sessions through command-line flags:
# New session each time (default)
grok -p "Hello"
# Resume an existing session by ID (errors if it does not exist)
grok -p "Continue where we left off" -r <session-id>
# Resume an existing session by ID or title (errors if it does not exist)
grok -p "Continue where we left off" -r <session-id-or-title>
# Continue the most recent session in the current directory
grok -p "What were we doing?" -c
```
In headless mode, resume an existing session with `-r`/`--resume`, which errors if the session does not exist, or continue the most recent session in the current directory with `-c`/`--continue`. Pass the session ID from JSON output (see below) to `-r`.
In headless mode, resume an existing session with `-r`/`--resume`, which errors if the session does not exist, or continue the most recent session in the current directory with `-c`/`--continue`. A non-ID value is matched against session titles for the current directory, ignoring letter case (a sole manually renamed match wins among duplicates; remaining duplicates error with their IDs; UUID-shaped values always take the ID path) — scripts should pass the session ID from JSON output (see below) to `-r`.
Use `-s`/`--session-id` only to **create** a new session with a **UUID** (errors if the value is not a UUID, or if that ID already has a session under the target session directory). It does **not** resume an existing session — that was the old hidden upsert behavior; use `-r`/`-c` instead. Combine `-s` with `-r`/`-c` only when also passing `--fork-session` (forks history into a new ID; optional `-s` names the child UUID). This matches Claude Codes anti-overwrite model (client preflight under the write cwd; sequential use is reliable, concurrent same-ID is best-effort).

View file

@ -45,6 +45,18 @@ To block specific files (e.g. `.env` or credential paths) on top of a profile, d
**strict** -- The most restrictive profile, for reviewing untrusted code. The agent can only read files within the current working directory and essential system paths. Writes are limited to CWD, `~/.grok/`, and temp directories. Child-process network access is blocked on Linux (no-op on macOS).
### Direct global hook write protection
Under `workspace`, `read-only`, and `strict` (and custom profiles that extend those bases), the Grok state directory remains writable for session/runtime files, but the kernel **write-denies** the Grok-owned direct disk paths used as user-global hook sources (they stay readable):
- `~/.grok/hooks/` (hook directory)
- `~/.grok/hooks-paths` (registry file; not loaded as hook JSON — only its absolute targets are)
- Absolute targets listed in `hooks-paths` (relative lines are ignored; missing targets refuse sandbox start)
On first launch under these profiles, Grok creates a real empty `hooks/` directory and empty `hooks-paths` file when they are missing (never symlinks or wrong types). Claude/Cursor global settings are **not** covered by this write-deny; discovery of those vendors remains separately gated by compatibility settings.
A symlinked `$GROK_HOME` or a `hooks-paths` entry with a symlink component is refused at sandbox start (prevents retargeting). Existing parent directories of protected paths are pinned so they cannot be renamed out from under the deny (siblings remain writable). On Linux, nested user namespaces are disabled inside bubblewrap so mount binds cannot be rearranged. Project hooks remain gated by folder trust. The `devbox` profile does not apply this protection (disposable VMs). Profiles that require it refuse to start if the kernel policy cannot be applied (including Linux without verified read-only mounts).
---
## Custom Profiles
@ -191,6 +203,25 @@ In practice, on Linux this means:
---
## Shell Environment Policy
The sandbox controls which files and network a subprocess can reach. The top-level `[shell_environment_policy]` table controls which environment variables it inherits, so a tool command the model runs cannot read a secret that happens to sit in your shell environment.
```toml
[shell_environment_policy]
inherit = "core" # all (default) | core | none
ignore_default_excludes = false # also drop *KEY* / *SECRET* / *TOKEN*
exclude = ["ACME_*", "CI_*"] # drop these names
include_only = ["PATH", "HOME"] # if set, keep only these names
set = { MY_FLAG = "1" } # force these values
```
Grok builds the child environment in order: it starts from `inherit` (`all` keeps everything, `core` keeps a small platform set such as `PATH` and `HOME`, `none` starts empty); drops the built-in secret patterns `*KEY*`, `*SECRET*`, and `*TOKEN*` unless `ignore_default_excludes = true`; drops any `exclude` matches; applies `set`; and, when `include_only` is non-empty, keeps only the matching names. Patterns are case-insensitive globs (`*`, `?`).
The default (`inherit = "all"`, `ignore_default_excludes = true`) leaves the environment untouched, so nothing changes until you configure a policy. On the non-persistent backend the policy also filters variables captured from your login shell, so an `.rc` file export cannot slip a secret past `exclude` or `include_only`. The persistent shell is one exception: it applies the policy to its base environment, but variables that an `.rc` file exports during login are replayed from a snapshot and are not re-filtered, so keep secrets out of shell startup files there. Enforcement covers the bash tool and terminals on macOS, Linux, and Windows.
---
## Event Logging
Sandbox events are logged to `~/.grok/sandbox-events.jsonl` for debugging. Events include:

View file

@ -23,6 +23,28 @@ that appear only as silence during capture.
`/terminal-setup`, `/terminal-check`, and `/terminal-info` remain aliases for
`/doctor`.
When Doctor finds an explicit unhealthy tmux setting, `/doctor fix` lists the
available automatic fixes. Apply one named fix at a time, for example
`/doctor fix tmux-clipboard` or `grok doctor fix dcs-passthrough --yes`.
Doctor can persist these three tmux options:
- `terminal.tmux-clipboard``set -g set-clipboard on`
- `terminal.dcs-passthrough``set -wg allow-passthrough on`
- `terminal.tmux-extended-keys``set -g extended-keys on`
A tmux fix edits only the persistent config on the computer hosting the affected
tmux server, including remote sessions. Plain tmux uses the real
`$HOME/.tmux.conf`; Byobu-tmux uses its effective `BYOBU_CONFIG_DIR` and refuses
to guess if that directory is unavailable or unsafe. Grok preserves the file's
line endings and mode, makes a backup when changing an existing file, and
refuses conflicting or ambiguous direct assignments.
Grok deliberately does **not** run `tmux source-file` or change the live tmux
server. Reload with the exact command shown after apply, or detach and reattach,
then run `/doctor` again. Until reload, the live finding is expected to remain.
The conservative config scan checks direct global assignments only; review
sourced files, conditionals, plugins, and generated tmux setup yourself.
---
## Detected Terminals