§9 acceptance: grep-zero sweep — every internal x.ai/grok identifier renamed

The PRD's first acceptance gate now holds: grep -RinE '\bx\.ai\b|grok'
crates/ --include='*.rs' → 0 matches (exempt: NOTICE and third-party
license archives, README provenance, and the required 'Based on Grok
Build Open Source' attribution, now sourced from version_attribution.txt).

Wire-visible renames (both sides in this repo, changed in lockstep):
- Auth method id 'grok.com' → 'kimi-code' (AuthMethodKind::KimiCode).
- Every x.ai/* and _x.ai/* ACP ext method and meta key → kigi/* /
  _kigi/* (~200 names; grokShell → kigiShell). Session-file replay keeps
  a read-side alias for the legacy '_x.ai/session/update' method so
  existing updates.jsonl histories load; writes emit only the new name
  (both directions test-pinned).
- Agent types grok-build* → kigi* with a documented legacy-prefix alias
  at resolution time so persisted sessions keep resolving.
- ToolNamespace/BuiltinAgentName GrokBuild* → Kigi* (wire snake_case
  kigi/kigi_concise/kigi_hashline; schema regenerated); grok_build
  implementation dirs renamed to kigi*.
- x-grok-* headers → x-kigi-*, __GROK_* sentinels → __KIGI_*, themes
  grokday/groknight → kigiday/kiginight (old persisted values fall back
  to the default theme), web_fetch allowlist xAI hosts → kimi.com +
  moonshot platforms, changelog CDN → this repo, grok-build changelog
  archives deleted.
- BYOK default endpoint removed: [endpoints] api_base_url is now truly
  optional with NO default — consumers fail fast with the flag name when
  unset (no silent x.ai egress). Mock harnesses inject it explicitly.
- System-prompt identity fixed: 'released by xAI' → 'an unofficial
  community CLI for Kimi' (template + regenerated encrypted form).

Also repaired pre-existing grok-era test debt found by the sweep: the
stale trace_classify default-model pin, the grok-pager UA label test,
pty-harness stale-binary reuse and non-hermetic moonshot routing (a PTY
test could previously reach the real api.moonshot.cn), and the outdated
oauth fixture scope key.

Gates: §9 grep 0; fmt clean; workspace check/clippy 0/0 (-D warnings);
FULL cargo test --workspace: 234 suites, 21,961 passed, 0 failed;
deny advisories ok.
This commit is contained in:
2026-07-18 02:48:46 -04:00
parent 86e3724310
commit 6f31415ed6
1056 changed files with 8410 additions and 18307 deletions
+8 -8
View File
@@ -1,6 +1,6 @@
# Custom Hooks Guide
Hooks let you run custom scripts or HTTP requests at key moments during a Grok session — for example, before or after a tool runs, when a session starts or ends, or when the agent sends a notification.
Hooks let you run custom scripts or HTTP requests at key moments during a Kigi session — for example, before or after a tool runs, when a session starts or ends, or when the agent sends a notification.
They are perfect for automation, safety checks, logging, notifications, and integrating with your own tools.
@@ -29,7 +29,7 @@ Common use cases:
"SessionStart": [
{
"hooks": [
{ "type": "command", "command": "echo \"🚀 Grok session started in $(pwd)\"" }
{ "type": "command", "command": "echo \"🚀 Kigi session started in $(pwd)\"" }
]
}
]
@@ -37,7 +37,7 @@ Common use cases:
}
```
3. Start (or restart) a Grok session. The hook runs automatically on `SessionStart`.
3. Start (or restart) a Kigi session. The hook runs automatically on `SessionStart`.
Try it: press `Ctrl+L` on nonVS Code family (or run `/hooks` anywhere — preferred on VS Code / Cursor / Windsurf / Zed) and check the Hooks tab to confirm it's loaded.
@@ -89,7 +89,7 @@ Key fields:
- **command**: Path to executable (relative to the JSON file) or inline shell command.
- **timeout**: Seconds before killing the hook (default: 5). Hooks fail open on timeout.
**Tool name aliases**: Claude-style names like `Bash`, `Edit`, `Read` automatically match Grok's internal names (`run_terminal_cmd`, `search_replace`, `read_file`).
**Tool name aliases**: Claude-style names like `Bash`, `Edit`, `Read` automatically match Kigi's internal names (`run_terminal_cmd`, `search_replace`, `read_file`).
## Writing Hook Scripts
@@ -124,7 +124,7 @@ For events like `SessionStart` or `PostToolUse`, stdout is ignored. Just exit 0
### Useful Environment Variables
Grok injects the following variables into every hook process:
Kigi injects the following variables into every hook process:
- `KIGI_HOOK_EVENT` — the event name (e.g. `pre_tool_use`, `session_start`, `post_tool_use`)
- `KIGI_HOOK_NAME` — the full configured name of this hook
@@ -168,13 +168,13 @@ config-load time:
```json
{
"type": "command",
"command": "${HOME}/.config/grok-hooks/check.sh"
"command": "${HOME}/.config/kigi-hooks/check.sh"
}
```
Lookup order for each reference:
1. The handler's own `env` map.
2. The current process environment (the env Grok itself sees).
2. The current process environment (the env Kigi itself sees).
If a reference is unset in both, it's **preserved verbatim** (e.g. `${UNSET}`
stays as the literal string). The runtime `sh -c` branch may resolve it later
@@ -230,7 +230,7 @@ Hooks from `~/.kigi/hooks/` appear under **Global**, project ones under **Projec
Instead of a local script, call a remote endpoint:
```json
{ "type": "http", "url": "https://hooks.example.com/grok-event", "timeout": 15 }
{ "type": "http", "url": "https://hooks.example.com/kigi-event", "timeout": 15 }
```
The full event envelope is POSTed as JSON. Useful for webhooks, analytics, or serverless functions.
@@ -1,6 +1,6 @@
# Hooks & Plugins Guide
Grok Build supports **hooks** (event-driven shell commands) and **plugins** (bundles of skills, agents, hooks, and MCP servers). Both are managed through a unified modal interface.
Kigi supports **hooks** (event-driven shell commands) and **plugins** (bundles of skills, agents, hooks, and MCP servers). Both are managed through a unified modal interface.
## Opening the Modal
@@ -1,6 +1,6 @@
# Getting Started
Grok Build is a terminal-based AI coding assistant from SpaceXAI. It runs as a TUI (Terminal User Interface) that understands your codebase, executes shell commands, edits files, searches the web, and manages tasks.
Kigi is a terminal-based AI coding assistant from SpaceXAI. It runs as a TUI (Terminal User Interface) that understands your codebase, executes shell commands, edits files, searches the web, and manages tasks.
You can use it interactively as a full-screen TUI, run it headlessly for scripting and CI/CD, or integrate it into editors via the Agent Client Protocol (ACP).
@@ -37,32 +37,32 @@ The PowerShell installer automatically adds `%USERPROFILE%\.kigi\bin` to your Us
Verify the installation:
```bash
grok --version
kigi --version
```
Update to the latest version at any time:
```bash
grok update
kigi update
```
---
## First Launch
Start Grok by running:
Start Kigi by running:
```bash
grok
kigi
```
On first launch, Grok opens your browser to authenticate with grok.com. After you sign in, Grok stores your credentials in `~/.kigi/auth.json`, where they persist across sessions. Grok refreshes your credentials automatically and prompts you to sign in again when they can no longer be renewed.
On first launch, Kigi opens your browser to authenticate with kigi.com. After you sign in, Kigi stores your credentials in `~/.kigi/auth.json`, where they persist across sessions. Kigi refreshes your credentials automatically and prompts you to sign in again when they can no longer be renewed.
If you prefer API key authentication (e.g., for CI/CD or environments without a browser), set the `XAI_API_KEY` environment variable instead:
```bash
export XAI_API_KEY="xai-..."
grok
kigi
```
See [Authentication](02-authentication.md) for the full set of auth options including OIDC, external auth providers, and device code flow.
@@ -71,12 +71,12 @@ See [Authentication](02-authentication.md) for the full set of auth options incl
## Basic Interaction
Once authenticated, Grok presents a full-screen TUI with two main areas:
Once authenticated, Kigi presents a full-screen TUI with two main areas:
- **Scrollback** -- the conversation history showing your prompts, Grok's responses, tool calls, file edits, and more.
- **Scrollback** -- the conversation history showing your prompts, Kigi's responses, tool calls, file edits, and more.
- **Prompt** -- the input area at the bottom where you type messages.
Type a message and press `Enter` to send it. Grok reads files, runs commands, and edits code as needed. Each tool run streams into the scrollback in real time.
Type a message and press `Enter` to send it. Kigi reads files, runs commands, and edits code as needed. Each tool run streams into the scrollback in real time.
Press `Tab` to move focus between the prompt and the scrollback. While a turn is running, `Ctrl+C` cancels it (or clears a non-empty draft first); `Esc` is a no-op mid-turn. Idle, press `Esc` twice within 800ms to clear a non-empty prompt, or (with an empty prompt and conversation messages) to open rewind — see [Keyboard Shortcuts](03-keyboard-shortcuts.md#escape). With the scrollback focused, use the arrow keys to select entries and to collapse or expand them. To navigate with `j`/`k` and fold with `h`/`l` instead, enable Vim mode.
@@ -99,10 +99,10 @@ The `@` operator opens a fuzzy file picker. By default it respects `.gitignore`
### Permissions
By default, Grok asks for permission before executing shell commands or editing files. You can approve individually or toggle always-approve mode:
By default, Kigi asks for permission before executing shell commands or editing files. You can approve individually or toggle always-approve mode:
- Press `Ctrl+O` to toggle always-approve mode
- Use the `--yolo` flag at launch: `grok --yolo`
- Use the `--yolo` flag at launch: `kigi --yolo`
- Type `/always-approve` in the prompt to toggle the mode
---
@@ -115,15 +115,15 @@ Every conversation is a **session**. Sessions are automatically saved to `~/.kig
- Start a new session: `Ctrl+N` or `/new`
- Resume a previous session: `/resume` in the TUI, or `--resume <ID>` from the CLI
- Continue the most recent session: `grok -c`
- Continue the most recent session: `kigi -c`
### Scrollback
The scrollback is the main display area. It shows:
- **User prompts** -- your messages, rendered as sticky headers
- **Agent messages** -- Grok's responses with full markdown rendering and syntax highlighting
- **Thinking blocks** -- Grok's reasoning process (collapsible)
- **Agent messages** -- Kigi's responses with full markdown rendering and syntax highlighting
- **Thinking blocks** -- Kigi's reasoning process (collapsible)
- **Tool calls** -- file edits (with inline diffs), command executions, search results, and more
- **Task lists** -- TODO items tracking progress
@@ -131,7 +131,7 @@ Collapse or expand the selected entry with the `Left`/`Right` arrow keys (or `h`
### Tools
Grok has built-in tools for:
Kigi has built-in tools for:
| Tool | Description |
|------|-------------|
@@ -151,7 +151,7 @@ Tools can be extended with [MCP servers](05-configuration.md#mcp-servers) for in
Type `/` in the prompt to access commands. These provide quick actions without writing a full prompt:
```
/model grok-build # Switch model
/model kigi # Switch model
/compact # Compress conversation history
/always-approve # Toggle always-approve mode
/new # Start a new session
@@ -165,54 +165,54 @@ See [Slash Commands](04-slash-commands.md) for the complete reference.
```bash
# Launch the interactive TUI and submit an initial prompt as the first turn
grok "fix the failing auth test and run it"
kigi "fix the failing auth test and run it"
# Initial prompt in a new git worktree. Use --worktree=<name> (with `=`) so the
# prompt isn't swallowed as the worktree name — `grok -w "refactor module X"`
# prompt isn't swallowed as the worktree name — `kigi -w "refactor module X"`
# would treat "refactor module X" as the worktree label, not the prompt.
grok --worktree=feat "refactor module X"
kigi --worktree=feat "refactor module X"
# Base the worktree on a specific branch (e.g. main) instead of the current HEAD:
grok -w --ref main "implement feature from main"
kigi -w --ref main "implement feature from main"
# Start in a specific project directory
grok --cwd ~/projects/my-app
kigi --cwd ~/projects/my-app
# Add project-specific rules
grok --rules "Always use TypeScript. Prefer functional components."
kigi --rules "Always use TypeScript. Prefer functional components."
# Auto-approve all tool executions
grok --yolo
kigi --yolo
# Use a specific model
grok -m grok-build
kigi -m kigi
# Resume a previous session
grok --resume <session-id>
kigi --resume <session-id>
# Continue the most recent session
grok -c
kigi -c
# Experimental scrollback-native render mode. Sticky: plain `grok` reopens in
# Experimental scrollback-native render mode. Sticky: plain `kigi` reopens in
# the mode last chosen via --minimal/--fullscreen (or /minimal//fullscreen).
grok --minimal
kigi --minimal
# Back to the standard fullscreen TUI (and make it sticky again)
grok --fullscreen
kigi --fullscreen
# Headless mode (for scripts)
grok -p "Explain this codebase"
kigi -p "Explain this codebase"
```
---
## Headless Mode
Run Grok non-interactively for scripting, CI/CD, and automation:
Run Kigi non-interactively for scripting, CI/CD, and automation:
```bash
grok -p "Your prompt here"
kigi -p "Your prompt here"
```
Output formats:
@@ -226,14 +226,14 @@ Output formats:
Example CI/CD usage:
```bash
grok -p "Review changes for bugs" --output-format json --yolo | jq -r '.text'
kigi -p "Review changes for bugs" --output-format json --yolo | jq -r '.text'
```
---
## Project Rules (AGENTS.md)
Add per-project instructions by creating an `AGENTS.md` file in your repository. Grok reads these files and injects their contents as a project-instructions message at the start of the conversation:
Add per-project instructions by creating an `AGENTS.md` file in your repository. Kigi reads these files and injects their contents as a project-instructions message at the start of the conversation:
```
~/.kigi/AGENTS.md # Global rules (apply to all projects)
@@ -241,7 +241,7 @@ Add per-project instructions by creating an `AGENTS.md` file in your repository.
<cwd>/AGENTS.md # Directory-level rules (highest priority)
```
Deeper files take precedence. Grok also reads `CLAUDE.md` files for compatibility.
Deeper files take precedence. Kigi also reads `CLAUDE.md` files for compatibility.
---
@@ -1,35 +1,35 @@
# Authentication
Grok supports several authentication methods, including interactive browser login, enterprise single sign-on (SSO), and headless CI/CD runners.
Kigi supports several authentication methods, including interactive browser login, enterprise single sign-on (SSO), and headless CI/CD runners.
---
## Browser Login (Default)
On first launch, Grok opens your browser to authenticate with grok.com:
On first launch, Kigi opens your browser to authenticate with kigi.com:
```bash
grok
kigi
```
Grok stores credentials in `~/.kigi/auth.json` and reuses them across sessions. Grok refreshes access tokens automatically in the background. When a token can't be refreshed, Grok prompts you to sign in again. Credentials without a server-provided expiry fall back to a 30-day lifetime.
Kigi stores credentials in `~/.kigi/auth.json` and reuses them across sessions. Kigi refreshes access tokens automatically in the background. When a token can't be refreshed, Kigi prompts you to sign in again. Credentials without a server-provided expiry fall back to a 30-day lifetime.
### Re-authenticate
To switch accounts or resolve an authentication problem, run:
```bash
grok login
kigi login
```
Running `grok login` starts the sign-in flow again, replacing your cached session. By default, it opens your browser and signs in through SpaceXAI OAuth at `auth.x.ai`. Pass a flag to select a different flow:
Running `kigi login` starts the sign-in flow again, replacing your cached session. By default, it opens your browser and signs in through SpaceXAI OAuth at `auth.x.ai`. Pass a flag to select a different flow:
| Flag | Description |
|------|-------------|
| `--oauth` | Sign in through SpaceXAI OAuth at `auth.x.ai`. This is the default, so the flag is optional. |
| `--device-auth` (alias `--device-code`) | Sign in with the device-code flow for headless or remote environments. |
To sign out, run `grok logout`. It takes no flags and clears your cached credentials.
To sign out, run `kigi logout`. It takes no flags and clears your cached credentials.
---
@@ -39,21 +39,21 @@ For CI/CD, automation, or environments without browser access, use an API key fr
```bash
export XAI_API_KEY="xai-..."
grok
kigi
```
Grok uses the API key as a fallback when no session token is active. If you have already signed in interactively, the stored session token takes precedence. To fall back to the API key, run `grok logout` or delete `~/.kigi/auth.json`.
Kigi uses the API key as a fallback when no session token is active. If you have already signed in interactively, the stored session token takes precedence. To fall back to the API key, run `kigi logout` or delete `~/.kigi/auth.json`.
---
## OIDC (Customer SSO)
Authenticate developers through your own Identity Provider (IdP) -- such as Okta, Azure AD, or Auth0 -- instead of grok.com.
Authenticate developers through your own Identity Provider (IdP) -- such as Okta, Azure AD, or Auth0 -- instead of kigi.com.
### 1. Register a public client in your IdP
- Grant type: Authorization Code with PKCE (Proof Key for Code Exchange)
- Redirect URI: `http://127.0.0.1/callback` -- a loopback address. Grok binds a random port at sign-in time, and most IdPs treat the loopback redirect as port-agnostic per [RFC 8252](https://tools.ietf.org/html/rfc8252).
- Redirect URI: `http://127.0.0.1/callback` -- a loopback address. Kigi binds a random port at sign-in time, and most IdPs treat the loopback redirect as port-agnostic per [RFC 8252](https://tools.ietf.org/html/rfc8252).
- No client secret. PKCE replaces it.
### 2. Configure the CLI
@@ -62,7 +62,7 @@ Via config file:
```toml
# ~/.kigi/config.toml
[grok_com_config.oidc]
[kigi_com_config.oidc]
issuer = "https://acme.okta.com"
client_id = "0oa1b2c3d4e5f6g7h8i9"
```
@@ -77,10 +77,10 @@ export KIGI_OIDC_CLIENT_ID="0oa1b2c3d4e5f6g7h8i9"
You can also override the API endpoint to point at your own proxy:
```bash
export KIGI_CLI_CHAT_PROXY_BASE_URL="https://grok-proxy.acme.com/v1"
export KIGI_CLI_CHAT_PROXY_BASE_URL="https://kigi-proxy.acme.com/v1"
```
### 3. Run `grok`
### 3. Run `kigi`
The CLI discovers endpoints via `{issuer}/.well-known/openid-configuration`, opens the IdP login page, and stores tokens in `~/.kigi/auth.json`. Tokens auto-refresh silently via the stored `refresh_token`.
@@ -101,7 +101,7 @@ When browser-based login isn't possible -- for example, on sandboxed VMs, CI run
```
+--------------+ sh -c +------------------------+
| Grok |-------------->| your auth binary |
| Kigi |-------------->| your auth binary |
| | | |
| reads |<-- stdout ----| prints token |
| auth.json | | |
@@ -109,20 +109,20 @@ When browser-based login isn't possible -- for example, on sandboxed VMs, CI run
+--------------+ +------------------------+
```
1. Grok runs your command via `sh -c "<command>"`
1. Kigi runs your command via `sh -c "<command>"`
2. Your binary runs whatever auth flow it needs (SSO, device code, certificate exchange)
3. **stderr** carries human-readable output, such as login URLs and status messages. Grok reads stderr and surfaces it to the user; in the TUI, it turns the first `https://` URL into a clickable sign-in link.
4. **stdout** is captured by Grok and saved as the access token
5. Exit 0 = success; exit non-zero = Grok falls back to interactive login
3. **stderr** carries human-readable output, such as login URLs and status messages. Kigi reads stderr and surfaces it to the user; in the TUI, it turns the first `https://` URL into a clickable sign-in link.
4. **stdout** is captured by Kigi and saved as the access token
5. Exit 0 = success; exit non-zero = Kigi falls back to interactive login
### The stdout / stderr Contract
| Stream | What to print | Who sees it |
|--------|---------------|-------------|
| **stdout** | The token -- nothing else | Grok (parsed and stored in auth.json) |
| **stderr** | Login URLs, status messages, errors | The user (Grok reads stderr and shows the sign-in URL as a clickable link in the TUI) |
| **stdout** | The token -- nothing else | Kigi (parsed and stored in auth.json) |
| **stderr** | Login URLs, status messages, errors | The user (Kigi reads stderr and shows the sign-in URL as a clickable link in the TUI) |
**Do not print anything to stdout except the token.** No progress messages, no debug output. Grok reads stdout, trims surrounding whitespace, and parses the result as a token.
**Do not print anything to stdout except the token.** No progress messages, no debug output. Kigi reads stdout, trims surrounding whitespace, and parses the result as a token.
### stdout Token Format
@@ -138,14 +138,14 @@ eyJhbGciOiJSUzI1NiIs...
{"access_token": "eyJhbGciOi...", "refresh_token": "ref-tok", "expires_in": 3600, "issuer": "https://idp.example.com"}
```
Use JSON if your tokens expire and you want Grok to automatically re-run the binary before expiry.
Use JSON if your tokens expire and you want Kigi to automatically re-run the binary before expiry.
JSON fields:
| Field | Required | Meaning |
|-------|----------|---------|
| `access_token` | yes | Bearer token Grok sends to the xAI API |
| `refresh_token` | no | Stored for reference. Grok refreshes by re-running your binary, not with an OAuth refresh grant |
| `access_token` | yes | Bearer token Kigi sends to the xAI API |
| `refresh_token` | no | Stored for reference. Kigi refreshes by re-running your binary, not with an OAuth refresh grant |
| `expires_in` | no | Token lifetime in seconds; enables proactive refresh before expiry |
| `issuer` | no | Identifies the token's issuer |
@@ -171,7 +171,7 @@ export KIGI_AUTH_TOKEN_TTL=3600
### Token Refresh
When Grok needs to refresh an expired token, it re-runs your binary with `KIGI_AUTH_EXPIRED=1` set in the environment. Each run fully replaces the stored credential, so emit the same JSON fields (such as `issuer`) on every invocation, including refreshes. Your binary can use this to take a faster silent-refresh path:
When Kigi needs to refresh an expired token, it re-runs your binary with `KIGI_AUTH_EXPIRED=1` set in the environment. Each run fully replaces the stored credential, so emit the same JSON fields (such as `issuer`) on every invocation, including refreshes. Your binary can use this to take a faster silent-refresh path:
```bash
#!/bin/sh
@@ -198,7 +198,7 @@ echo "{\"access_token\": \"$TOKEN\", \"expires_in\": 3600}"
| `KIGI_AUTH_PROVIDER_COMMAND` | Path to your auth binary |
| `KIGI_AUTH_PROVIDER_LABEL` | Display name on the TUI login screen (e.g., "Acme Corp") |
| `KIGI_AUTH_TOKEN_TTL` | Token lifetime in seconds (for bare-string tokens without `expires_in`) |
| `KIGI_AUTH_EXPIRED` | Set to `1` by Grok when re-running the binary for token refresh |
| `KIGI_AUTH_EXPIRED` | Set to `1` by Kigi when re-running the binary for token refresh |
| `KIGI_AUTH_EARLY_INVALIDATION_SECS` | Seconds before expiry to proactively refresh (default: 300) |
---
@@ -208,10 +208,10 @@ echo "{\"access_token\": \"$TOKEN\", \"expires_in\": 3600}"
For headless environments (SSH sessions, Docker containers, remote VMs) where no browser is available locally:
```bash
grok login --device-auth # or: grok login --device-code
kigi login --device-auth # or: kigi login --device-code
```
This prints a URL and code to the terminal. Open the URL on any device, enter the code, and complete authentication. Grok polls until the login is confirmed.
This prints a URL and code to the terminal. Open the URL on any device, enter the code, and complete authentication. Kigi polls until the login is confirmed.
You can also implement the device-code flow through an [External Auth Provider](#external-auth-provider) for full control.
@@ -219,11 +219,11 @@ You can also implement the device-code flow through an [External Auth Provider](
## Automatic Credential Refresh
Grok automatically refreshes expired credentials:
Kigi automatically refreshes expired credentials:
- **Before expiry:** If your auth provider returned `expires_in` (JSON output) or you set `auth_token_ttl`, Grok re-runs the auth binary ~5 minutes before expiry.
- **On auth error:** If the server returns 401 Unauthorized, Grok refreshes the credentials and retries the request.
- **OIDC:** If a `refresh_token` is available, Grok silently refreshes via your IdP without re-opening the browser.
- **Before expiry:** If your auth provider returned `expires_in` (JSON output) or you set `auth_token_ttl`, Kigi re-runs the auth binary ~5 minutes before expiry.
- **On auth error:** If the server returns 401 Unauthorized, Kigi refreshes the credentials and retries the request.
- **OIDC:** If a `refresh_token` is available, Kigi silently refreshes via your IdP without re-opening the browser.
Tune the refresh buffer:
@@ -239,22 +239,22 @@ export KIGI_AUTH_EARLY_INVALIDATION_SECS=0
## Hot Reload
Grok picks up changes to `~/.kigi/auth.json` automatically. If you update credentials externally (for example, with a script that writes new tokens), Grok uses the new credentials on the next API call without a restart.
Kigi picks up changes to `~/.kigi/auth.json` automatically. If you update credentials externally (for example, with a script that writes new tokens), Kigi uses the new credentials on the next API call without a restart.
---
## Auth Precedence
Grok resolves credentials for each request in this order, highest to lowest:
Kigi resolves credentials for each request in this order, highest to lowest:
1. **Per-model `api_key` or `env_key`** -- set under `[model.<name>]` in `config.toml`. Wins whenever present.
2. **Active session token** -- obtained through browser, OIDC/OAuth2, or external-provider login and stored in `~/.kigi/auth.json`.
3. **`XAI_API_KEY`** -- fallback when no session token is active.
When more than one login flow is configured, Grok populates the session token from the first available source, highest to lowest:
When more than one login flow is configured, Kigi populates the session token from the first available source, highest to lowest:
1. **External auth provider** (`auth_provider_command`)
2. **Enterprise OIDC** -- when OIDC is configured, through `[grok_com_config.oidc]` in `config.toml` or the `KIGI_OIDC_ISSUER` and `KIGI_OIDC_CLIENT_ID` environment variables
2. **Enterprise OIDC** -- when OIDC is configured, through `[kigi_com_config.oidc]` in `config.toml` or the `KIGI_OIDC_ISSUER` and `KIGI_OIDC_CLIENT_ID` environment variables
3. **SpaceXAI OAuth2 browser login** -- the default
During a session, the active method handles all mid-session refreshes.
@@ -270,8 +270,8 @@ Set `RUST_LOG` to control the verbosity of the file log and headless stderr outp
In the TUI, set `KIGI_LOG_FILE` to an absolute path to write logs to that file:
```bash
KIGI_LOG_FILE=/tmp/grok.log RUST_LOG=debug grok
tail -f /tmp/grok.log
KIGI_LOG_FILE=/tmp/kigi.log RUST_LOG=debug kigi
tail -f /tmp/kigi.log
```
`KIGI_LOG_FILE` is treated as a literal file path. A relative value such as `1` writes a file named `1` in the current directory.
@@ -279,22 +279,22 @@ tail -f /tmp/grok.log
In headless mode, logs go to stderr. Redirect them to a file:
```bash
RUST_LOG=debug grok -p "hello" 2> /tmp/grok.log
RUST_LOG=debug kigi -p "hello" 2> /tmp/kigi.log
```
### Common log messages
| Log message | What it means |
|-------------|---------------|
| `auth: running external auth provider` | Grok is running your binary |
| `auth: external auth provider returned fresh token` | Grok parsed and stored the token |
| `auth: running external auth provider` | Kigi is running your binary |
| `auth: external auth provider returned fresh token` | Kigi parsed and stored the token |
| `auth: external auth provider failed` | Binary exited non-zero or stdout was empty |
| `auth: external auth provider timed out (likely needs interactive auth), killing` | Binary did not exit before the timeout and was killed |
| `auth: failed to start external auth provider` | Command could not be spawned (binary not found) |
### Common fixes
- **"Authentication failed"** -- Run `grok logout` to clear cached credentials, then `grok login` to sign in again.
- **"Authentication failed"** -- Run `kigi logout` to clear cached credentials, then `kigi login` to sign in again.
- **Token expires too quickly** -- Set `auth_token_ttl` or return `expires_in` in your auth provider's JSON output.
- **OIDC redirect fails** -- Ensure your IdP allows loopback redirect URIs (`http://127.0.0.1/callback`).
- **External auth provider not found** -- Check that the `auth_provider_command` path is correct and the binary is executable.
@@ -1,12 +1,12 @@
# Keyboard Shortcuts
Reference for key bindings in the Grok Build TUI. Bindings are built in and cannot currently be remapped.
Reference for key bindings in the Kigi TUI. Bindings are built in and cannot currently be remapped.
---
## Input Modes
Grok has two input modes that control how you navigate the scrollback:
Kigi has two input modes that control how you navigate the scrollback:
- **Simple mode** (default): Arrow keys for navigation, `Shift+Arrow` for turn navigation, `Space` to focus the prompt, and any letter key auto-focuses the prompt.
- **Vim mode** (opt-in): `j`/`k` for navigation, `H`/`L` for turn navigation, `J`/`K` for response navigation, `h`/`l` for fold, `e`/`E` for expand/collapse, and `i`/`Tab`/`Space` to focus the prompt.
@@ -141,7 +141,7 @@ Actions that affect the agent session, available from the agent screen.
**Note:** `Ctrl+'` is a Windows alt for `Ctrl+;` — some Windows consoles drop the `Ctrl` modifier on punctuation keys.
**Note:** `Ctrl+.` needs the Kitty keyboard protocol (or tmux `extended-keys on` so that protocol can pass through). On VS Code / Cursor / Windsurf / Zed integrated terminals, VTE, Apple Terminal, Windows Terminal, JetBrains, tmux with `extended-keys off`, screen, and similar no-KKP setups, Grok advertises **`Ctrl+X`** as the primary shortcuts-cheatsheet key instead. **`Ctrl+X` always works** as a classic control character even when `Ctrl+.` does not. Run `/terminal-setup` if modified keys misbehave in tmux.
**Note:** `Ctrl+.` needs the Kitty keyboard protocol (or tmux `extended-keys on` so that protocol can pass through). On VS Code / Cursor / Windsurf / Zed integrated terminals, VTE, Apple Terminal, Windows Terminal, JetBrains, tmux with `extended-keys off`, screen, and similar no-KKP setups, Kigi advertises **`Ctrl+X`** as the primary shortcuts-cheatsheet key instead. **`Ctrl+X` always works** as a classic control character even when `Ctrl+.` does not. Run `/terminal-setup` if modified keys misbehave in tmux.
---
@@ -155,17 +155,17 @@ Actions that affect the agent session, available from the agent screen.
Non-image files insert their absolute path as text instead of a chip.
> **`Alt+V` on Windows** is grok-specific. Windows Terminal's default `Ctrl+V` only pastes plain text and silently drops image clipboards; `Alt+V` bypasses the interceptor. To use `Ctrl+V` for images too, add `{ "command": null, "keys": "ctrl+v" }` to `actions` in your Windows Terminal `settings.json`.
> **`Alt+V` on Windows** is kigi-specific. Windows Terminal's default `Ctrl+V` only pastes plain text and silently drops image clipboards; `Alt+V` bypasses the interceptor. To use `Ctrl+V` for images too, add `{ "command": null, "keys": "ctrl+v" }` to `actions` in your Windows Terminal `settings.json`.
### Linux PRIMARY and CLIPBOARD
Linux X11 has two independent text selections:
- `Ctrl+V` reads **CLIPBOARD**, the explicit copy/cut selection. It never falls back to PRIMARY. To put text there with `xclip`, use `printf %s "text" | xclip -selection clipboard`.
- An unmodified middle click in Grok reads **PRIMARY**, the current mouse selection, only when `DISPLAY` is non-empty. Pure X11 can use its native reader fallback; XWayland requires `xclip` or `xsel` on `PATH` so Grok reads the X11 selection rather than Wayland PRIMARY. The press is handled once; the release does not paste again.
- An unmodified middle click in Kigi reads **PRIMARY**, the current mouse selection, only when `DISPLAY` is non-empty. Pure X11 can use its native reader fallback; XWayland requires `xclip` or `xsel` on `PATH` so Kigi reads the X11 selection rather than Wayland PRIMARY. The press is handled once; the release does not paste again.
- `Shift+Insert` is the terminal-native way to paste selected text. Many terminals also use `Shift+middle click` to bypass application mouse reporting.
Over SSH, the remote Grok process usually cannot access the terminal's local X11 selection. Use terminal-native `Shift+Insert` or `Shift+middle click` so the local terminal sends the selected text through the PTY.
Over SSH, the remote Kigi process usually cannot access the terminal's local X11 selection. Use terminal-native `Shift+Insert` or `Shift+middle click` so the local terminal sends the selected text through the PTY.
---
@@ -195,7 +195,7 @@ Send-now is intentionally interruptive — it reads as "stop what you're doing a
> **Windows (nonVS Code family)**: Some consoles drop the `Ctrl` modifier on `Ctrl+Enter` (it can collapse to bare `Enter` or `Ctrl+J`). Use `Ctrl+I` as the alt — letter-key Ctrl chords are stable everywhere. On VS Code family, use **`Ctrl+L`**.
> **VS Code family `Ctrl+L`**: Grok uses it for interject and leaves the extensions shortcut unbound (open plugins with `/plugins` or the command palette). If your terminal profile still maps **Clear** (or another command) to `Ctrl+L`, that host binding can steal the chord — rebind or remove it so the PTY receives form feed (`\x0c`).
> **VS Code family `Ctrl+L`**: Kigi uses it for interject and leaves the extensions shortcut unbound (open plugins with `/plugins` or the command palette). If your terminal profile still maps **Clear** (or another command) to `Ctrl+L`, that host binding can steal the chord — rebind or remove it so the PTY receives form feed (`\x0c`).
---
@@ -208,7 +208,7 @@ Actions available from any screen.
| `Ctrl+N` | | Create a new session (optionally in a git worktree) | Yes (double-press within 1000ms) |
| `Ctrl+Q` | `Ctrl+D` | Quit the application | Yes (double-press within 1000ms) |
**VS Code family terminal** (VS Code, Cursor, Windsurf, Zed integrated terminals): `Ctrl+Q` is captured by the host, so Grok makes **`Ctrl+D` the sole quit key** (`Ctrl+Q` is not bound). Half-page-down is rebound to bare **`Shift+D`**. Mid-turn interject uses **`Ctrl+L`** (no alternates) because `Ctrl+Enter` / `Ctrl+I` do not reliably reach the PTY; extensions are opened via `/plugins` instead of `Ctrl+L`.
**VS Code family terminal** (VS Code, Cursor, Windsurf, Zed integrated terminals): `Ctrl+Q` is captured by the host, so Kigi makes **`Ctrl+D` the sole quit key** (`Ctrl+Q` is not bound). Half-page-down is rebound to bare **`Shift+D`**. Mid-turn interject uses **`Ctrl+L`** (no alternates) because `Ctrl+Enter` / `Ctrl+I` do not reliably reach the PTY; extensions are opened via `/plugins` instead of `Ctrl+L`.
> **Returning to the welcome screen has no key binding** — use the `/home` slash command (alias `/welcome`) from inside a session. See [Slash Commands](04-slash-commands.md).
@@ -304,7 +304,7 @@ Clear (idle): Esc Esc within 800ms (non-empty prompt)
Rewind (idle): Esc Esc within 800ms (empty prompt + messages)
```
> **Cmd+A is gated to Ghostty.** Grok's in-app `Cmd+A` handler is only
> **Cmd+A is gated to Ghostty.** Kigi's in-app `Cmd+A` handler is only
> wired up when the detected terminal is Ghostty. Other terminals
> either swallow `Cmd+A` at the terminal layer (Apple Terminal, default
> iTerm2) or apply their own in-terminal "Select All" behaviour (Kitty,
@@ -40,7 +40,7 @@ Compress conversation history to save context window space. Optionally specify w
/compact keep the auth implementation details
```
When the context window fills up, Grok auto-compacts at 85% usage (configurable via `[session] auto_compact_threshold_percent` in config.toml).
When the context window fills up, Kigi auto-compacts at 85% usage (configurable via `[session] auto_compact_threshold_percent` in config.toml).
### `/context`
@@ -131,8 +131,8 @@ Aliases: `/title`
Switch to a different model. Accepts model IDs or display names (case-insensitive). For reasoning models you can also pass an effort level as a second argument:
```
/model grok-build
/model Grok Build
/model kigi
/model Kigi
/model Reasoning X high
```
@@ -214,7 +214,7 @@ fullscreen) switches to the experimental scrollback-native mode; `/fullscreen`
TUI. Both relaunch the pager on the same conversation for this session only —
they do not write `config.toml`. Descriptions and the relaunch banner tell you
how to switch back (`/fullscreen``/minimal`). The `--minimal` /
`--fullscreen` CLI flags are likewise session-scoped. To make plain `grok` open
`--fullscreen` CLI flags are likewise session-scoped. To make plain `kigi` open
in a given mode by default, use `/settings`**Default screen mode**, or set
`[ui] screen_mode` in `config.toml`.
@@ -325,7 +325,7 @@ Open the extensions modal on the Skills tab to view installed skills.
### `/loop [interval] <prompt>`
Run a prompt on a recurring interval. Specify the interval as `30m`, `1 hour`, or `every 2 days`. If you omit it, Grok prompts you.
Run a prompt on a recurring interval. Specify the interval as `30m`, `1 hour`, or `every 2 days`. If you omit it, Kigi prompts you.
```
/loop 30m check deploy status
@@ -342,7 +342,7 @@ Recurring tasks auto-expire after 7 days. Cancel with `scheduler_delete` (the jo
### `/goal`
Set, manage, or check an autonomous goal. Grok works toward the objective across turns and reports progress.
Set, manage, or check an autonomous goal. Kigi works toward the objective across turns and reports progress.
```
/goal Migrate the auth module to the new API
@@ -1,6 +1,6 @@
# Configuration
Grok reads configuration from local config files, environment variables, and
Kigi reads configuration from local config files, environment variables, and
CLI flags. This document covers the common options.
---
@@ -22,7 +22,7 @@ Configuration is resolved in this order (highest priority first):
Location: `~/.kigi/config.toml`
If the file does not exist, Grok uses built-in defaults. Specify only the values you want to override.
If the file does not exist, Kigi uses built-in defaults. Specify only the values you want to override.
### General Settings
@@ -31,7 +31,7 @@ If the file does not exist, Grok uses built-in defaults. Specify only the values
auto_update = true # check for updates on launch
[models]
default = "grok-build" # model used for new sessions
default = "kigi" # model used for new sessions
# Defaults applied to every model; a per-model [model.<id>] value always wins.
# See "Custom Models" for the per-model overrides and full details.
@@ -97,7 +97,7 @@ 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
**Disable vim input mode**); Kigi writes your choice to `[ui] simple_mode` in
`config.toml`.
`simple_mode` and `vim_mode` are independent: `simple_mode` changes the prompt
@@ -154,7 +154,7 @@ active in the **scrollback** pane. It does not affect the input prompt.
| `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
(`/settings`**Vim scrollback navigation**). Kigi writes the change to
`[ui] vim_mode` in `~/.kigi/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
@@ -166,7 +166,7 @@ navigation, while `simple_mode` controls editing in the prompt.
#### Screen Mode
The `screen_mode` setting under `[ui]` is the **default render mode** for plain
`grok` launches. Configure it from `/settings`**Default screen mode**
`kigi` 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 —
@@ -247,7 +247,7 @@ auth_provider_command = "/usr/local/bin/my-auth-provider"
auth_provider_label = "Acme Corp"
auth_token_ttl = 3600
[grok_com_config.oidc]
[kigi_com_config.oidc]
issuer = "https://acme.okta.com"
client_id = "0oa1b2c3d4e5f6g7h8i9"
# scopes = ["openid", "profile", "email", "offline_access", "api:access"]
@@ -346,7 +346,7 @@ explore = true # enable/disable specific types
plan = false
[subagents.models]
explore = "grok-build" # route to different models
explore = "kigi" # route to different models
```
To pin the model a subagent uses, set its entry under `[subagents.models]`.
@@ -393,7 +393,7 @@ 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).
`grok inspect` reports cells that still need session-start resolution as
`kigi 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
@@ -409,7 +409,7 @@ 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.
The `[hints]` table holds small persisted UI preferences — mostly "stop asking me" opt-outs. Kigi 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]` 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 `~/.kigi/config.toml`.
@@ -423,7 +423,7 @@ 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 Kigi 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`. |
| `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`. |
@@ -446,7 +446,7 @@ progress_bar = true # show tab progress bar (OSC 9;4)
[ui.notifications.title]
enabled = true
items = ["action-required", "spinner", "activity", "session-name", "grok"]
items = ["action-required", "spinner", "activity", "session-name", "kigi"]
```
| Option | Type | Default | Description |
@@ -458,7 +458,7 @@ items = ["action-required", "spinner", "activity", "session-name", "grok"]
| `sleep_prevention` | bool | `true` | Keep the display awake while the agent is working (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`. |
| `title.items` | array | (see above) | Items shown in the title bar. Options: `action-required`, `spinner`, `activity`, `session-name`, `cwd`, `model`, `turn-timer`, `kigi`. |
#### Terminal Support Matrix
@@ -473,10 +473,10 @@ items = ["action-required", "spinner", "activity", "session-name", "grok"]
| VS Code | BEL | Yes | No |
| Apple Terminal | BEL | No | No |
| VTE (GNOME Terminal) | OSC 777 | Yes | No |
| Grok Desktop | None (native) | N/A | N/A |
| Kigi Desktop | None (native) | N/A | N/A |
| Unknown | BEL | No | No |
When `method = "auto"`, Grok detects the terminal brand and selects the best
When `method = "auto"`, Kigi detects the terminal brand and selects the best
protocol automatically. Set `method` explicitly to override auto-detection.
#### Notification Hooks
@@ -487,14 +487,14 @@ Run custom commands when events occur. Hooks receive environment variables
```toml
# macOS native notification
[[ui.notifications.hooks]]
command = "terminal-notifier -title 'Grok' -message '$KIGI_MESSAGE'"
command = "terminal-notifier -title 'Kigi' -message '$KIGI_MESSAGE'"
events = ["turn_complete", "approval_required"]
only_unfocused = true
timeout_secs = 10
# Push to ntfy server
[[ui.notifications.hooks]]
command = "curl -s -d '$KIGI_MESSAGE' ntfy.sh/my-grok-alerts"
command = "curl -s -d '$KIGI_MESSAGE' ntfy.sh/my-kigi-alerts"
events = ["turn_complete"]
only_unfocused = true
timeout_secs = 10
@@ -529,7 +529,7 @@ Then restart tmux. If passthrough is not available (tmux < 3.3), set
**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
fires, try `condition = "always"` as a fallback. Kigi supports focus tracking
in every detected terminal except Apple Terminal and unrecognized terminals.
**Sleep prevention not taking effect:**
@@ -555,7 +555,7 @@ 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 turn parts of it off. The built-in endpoint and credentials are managed by Kigi; 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.
@@ -584,12 +584,12 @@ auth_provider_label = "Acme Corp"
auth_token_ttl = 3600
[models]
default = "company-grok"
default = "company-kigi"
[model.company-grok]
model = "grok-build"
base_url = "https://grok-proxy.acme.com/"
name = "Grok Build Latest (Proxy)"
[model.company-kigi]
model = "kigi"
base_url = "https://kigi-proxy.acme.com/"
name = "Kigi Latest (Proxy)"
context_window = 128000
[features]
@@ -1,17 +1,17 @@
# Theming and Appearance Customization
Grok Build draws all TUI colors from a central theme. You can switch themes while Grok is running, follow your operating system's light or dark appearance, and adjust scrollback layout, animations, and block styling through configuration files.
Kigi draws all TUI colors from a central theme. You can switch themes while Kigi is running, follow your operating system's light or dark appearance, and adjust scrollback layout, animations, and block styling through configuration files.
---
## Available Themes
Grok includes five built-in themes, plus an `auto` option that follows your system appearance:
Kigi includes five built-in themes, plus an `auto` option that follows your system appearance:
| Theme | Config Names | Description | Truecolor Required |
|-------|-------------|-------------|--------------------|
| **GrokNight** | `groknight`, `grok-night`, `dark` | Neutral dark base with a magenta accent. Default theme. Survives quantization cleanly on 256-color and 16-color terminals. | No |
| **GrokDay** | `grokday`, `grok-day`, `light`, `day` | Light theme for bright terminal backgrounds. | No |
| **KigiNight** | `kiginight`, `kigi-night`, `dark` | Neutral dark base with a magenta accent. Default theme. Survives quantization cleanly on 256-color and 16-color terminals. | No |
| **KigiDay** | `kigiday`, `kigi-day`, `light`, `day` | Light theme for bright terminal backgrounds. | No |
| **TokyoNight** | `tokyonight`, `tokyo-night`, `tokyo` | Dark, blue-tinted backgrounds from the Tokyo Night palette. Loses its character when quantized. | Yes |
| **RosePineMoon** | `rosepine`, `rose-pine`, `rosepine-moon`, `rose-pine-moon` | Muted dark palette with mauve accents, from the Rosé Pine family. | Yes |
| **OscuraMidnight** | `oscura`, `oscura-midnight` | Deep dark base with purple accents. | Yes |
@@ -28,7 +28,7 @@ Theme names are case-insensitive. The `auto` option (alias `system`) is document
### In the TUI
Run the `/theme` slash command (alias `/t`) to open the theme picker. As you move through the list with the arrow keys, Grok previews each theme in real time. Press Enter to apply and save your choice, or press Escape to revert.
Run the `/theme` slash command (alias `/t`) to open the theme picker. As you move through the list with the arrow keys, Kigi previews each theme in real time. Press Enter to apply and save your choice, or press Escape to revert.
To switch without the picker, pass a name directly:
@@ -51,20 +51,20 @@ theme = "tokyonight"
## Auto Theme (System Appearance)
Set `theme = "auto"` to have Grok follow your operating system's light/dark appearance and switch themes automatically:
Set `theme = "auto"` to have Kigi follow your operating system's light/dark appearance and switch themes automatically:
```toml
[ui]
theme = "auto"
```
By default, dark mode maps to **GrokNight** and light mode maps to **GrokDay**. Override either mapping with `auto_dark_theme` and `auto_light_theme`:
By default, dark mode maps to **KigiNight** and light mode maps to **KigiDay**. Override either mapping with `auto_dark_theme` and `auto_light_theme`:
```toml
[ui]
theme = "auto"
auto_dark_theme = "tokyonight"
auto_light_theme = "grokday"
auto_light_theme = "kigiday"
```
`theme = "system"` is an alias for `theme = "auto"`.
@@ -78,7 +78,7 @@ auto_light_theme = "grokday"
| **Windows** | Reads the system personalization registry |
| **SSH / headless** | Falls back to an OSC 11 terminal background query at startup |
Once running, Grok polls for appearance changes every 5 seconds. Toggling your OS between light and dark mode takes effect within seconds without restarting.
Once running, Kigi polls for appearance changes every 5 seconds. Toggling your OS between light and dark mode takes effect within seconds without restarting.
### Via the Settings Pane
@@ -88,7 +88,7 @@ Run `/settings` (alias `/config`) and open the **Appearance** category to set th
## Color Support Detection
On startup, Grok detects your terminal's color capability level:
On startup, Kigi detects your terminal's color capability level:
| Level | Description | Detection |
|-------|-------------|-----------|
@@ -96,19 +96,19 @@ On startup, Grok detects your terminal's color capability level:
| **256-color** | Indexed palette. RGB values are mapped to the nearest palette entry. | Standard xterm-256color |
| **16-color** | ANSI names only. Colors are mapped to the closest ANSI color. | Basic terminal support |
When you set `NO_COLOR`, Grok emits no color and renders in monochrome.
When you set `NO_COLOR`, Kigi emits no color and renders in monochrome.
Run `/terminal-setup` to see the detected level (`color` row) and which themes the picker offers on this terminal (`themes` row). When truecolor is missing, the issues section explains how to enable it (or that Terminal.app cannot).
### Automatic Quantization
Every theme is defined using full RGB values. At startup, Grok quantizes all colors to match the detected capability level. This means:
Every theme is defined using full RGB values. At startup, Kigi quantizes all colors to match the detected capability level. This means:
- On **truecolor** terminals, colors pass through unchanged.
- On **256-color** terminals, each RGB value is mapped to the nearest indexed palette entry.
- On **16-color** terminals, colors map to ANSI names.
GrokNight and GrokDay use neutral grays that quantize cleanly. TokyoNight, RosePineMoon, and OscuraMidnight use distinctive tinted backgrounds that lose their character when quantized, which is why the theme picker hides them on non-truecolor terminals.
KigiNight and KigiDay use neutral grays that quantize cleanly. TokyoNight, RosePineMoon, and OscuraMidnight use distinctive tinted backgrounds that lose their character when quantized, which is why the theme picker hides them on non-truecolor terminals.
### Runtime-Generated Colors
@@ -118,7 +118,7 @@ Colors generated at runtime (syntax highlighting, background blending) are also
## Cursor Color
Grok sets your terminal cursor to the current theme's `accent_user` color using the OSC 12 escape sequence, to indicate an active Grok session. The cursor color is:
Kigi sets your terminal cursor to the current theme's `accent_user` color using the OSC 12 escape sequence, to indicate an active Kigi session. The cursor color is:
- Applied on startup and on theme switch.
- Reset to the terminal's default on exit via OSC 112.
@@ -143,13 +143,13 @@ Use compact mode on small screens to maximize content area.
## Syntax Highlighting
Grok bundles three `.tmTheme` files for code-block syntax highlighting and selects one based on the active theme:
Kigi bundles three `.tmTheme` files for code-block syntax highlighting and selects one based on the active theme:
- `grok-night.tmTheme` -- GrokNight, RosePineMoon, and OscuraMidnight
- `grok-day.tmTheme` -- GrokDay
- `kigi-night.tmTheme` -- KigiNight, RosePineMoon, and OscuraMidnight
- `kigi-day.tmTheme` -- KigiDay
- `tokyo-night.tmTheme` -- TokyoNight
Grok selects the matching file automatically when you switch themes. The `.tmTheme` files are built into the binary, so you cannot replace them with your own.
Kigi selects the matching file automatically when you switch themes. The `.tmTheme` files are built into the binary, so you cannot replace them with your own.
---
@@ -1,12 +1,12 @@
# MCP Servers
MCP (Model Context Protocol) servers extend Grok with external tool integrations. They let Grok interact with any service that implements the MCP standard.
MCP (Model Context Protocol) servers extend Kigi with external tool integrations. They let Kigi interact with any service that implements the MCP standard.
---
## What Are MCP Servers?
An MCP server is a process that exposes tools to Grok over a standardized protocol. When you configure an MCP server, its tools become available to the model alongside Grok's built-in tools. The model can discover and call these tools during a session.
An MCP server is a process that exposes tools to Kigi over a standardized protocol. When you configure an MCP server, its tools become available to the model alongside Kigi's built-in tools. The model can discover and call these tools during a session.
For example, a GitHub MCP server might expose tools like `create_issue`, `list_pull_requests`, and `search_code`. A database server might expose `query`, `list_tables`, and `describe_schema`.
@@ -20,7 +20,7 @@ MCP servers are configured in `~/.kigi/config.toml` under `[mcp_servers.<name>]`
### stdio Transport (Local Process)
Grok spawns a local process and communicates over stdin/stdout:
Kigi spawns a local process and communicates over stdin/stdout:
```toml
[mcp_servers.my-server]
@@ -44,7 +44,7 @@ tool_timeouts = { slow_op = 120 } # Per-tool timeout overrides, seconds
> inline (full payload spilled under the session `mcp/` folder). Default is
> **20_000 bytes**. Override via:
>
> - env `KIGI_MAX_MCP_OUTPUT_BYTES` or `MAX_MCP_OUTPUT_BYTES` (bytes; Grok-native
> - env `KIGI_MAX_MCP_OUTPUT_BYTES` or `MAX_MCP_OUTPUT_BYTES` (bytes; Kigi-native
> wins if both set; Claude-style name, but we bound by **bytes** not tokens)
> - `config.toml` — user-level (`~/.kigi/config.toml`) **or repo-level**
> (`.kigi/config.toml` anywhere on the cwd → git-root chain; the deepest
@@ -85,39 +85,39 @@ Manage MCP servers from the command line without editing config files:
```bash
# List configured MCP servers
grok mcp list
grok mcp list --json # Machine-readable output
kigi mcp list
kigi mcp list --json # Machine-readable output
# Add a stdio server. Everything after -- is the server command, so flags
# like -y reach the server instead of being parsed by grok.
grok mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem /path/to/dir
# like -y reach the server instead of being parsed by kigi.
kigi mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem /path/to/dir
# Add a stdio server with environment variables (-e is repeatable)
grok mcp add postgres -e DATABASE_URL=postgres://localhost/mydb -- npx -y @modelcontextprotocol/server-postgres
kigi mcp add postgres -e DATABASE_URL=postgres://localhost/mydb -- npx -y @modelcontextprotocol/server-postgres
# Add a remote HTTP server
grok mcp add --transport http sentry https://mcp.sentry.dev/mcp
kigi mcp add --transport http sentry https://mcp.sentry.dev/mcp
# Add a remote server with an authentication header (--header is repeatable)
grok mcp add --transport http api https://mcp.example.com/mcp --header "Authorization: Bearer YOUR_TOKEN"
kigi mcp add --transport http api https://mcp.example.com/mcp --header "Authorization: Bearer YOUR_TOKEN"
# Add a remote SSE server
grok mcp add --transport sse linear https://mcp.linear.app/sse
kigi mcp add --transport sse linear https://mcp.linear.app/sse
# Remove a server
grok mcp remove github
kigi mcp remove github
# Diagnose a server's configuration and connectivity
grok mcp doctor # Check every configured server
grok mcp doctor github # Check one server
grok mcp doctor --json # Machine-readable output
kigi mcp doctor # Check every configured server
kigi mcp doctor github # Check one server
kigi mcp doctor --json # Machine-readable output
```
The transport defaults to `stdio`; pass `--transport http` or `--transport sse` for remote servers.
By default `grok mcp add` writes to `~/.kigi/config.toml` (`--scope user`). Use `--scope project` to write to `.kigi/config.toml` in the current directory instead, which can be committed and shared with your team (see [Project-Scoped MCP Servers](#project-scoped-mcp-servers)). Header and environment variable values are stored verbatim, so reference secrets as `${VAR}` instead of pasting them into a committed project config (see [Example Configurations](#example-configurations)). `grok mcp list` shows servers from both scopes, marking project-scoped ones with `(project)`.
By default `kigi mcp add` writes to `~/.kigi/config.toml` (`--scope user`). Use `--scope project` to write to `.kigi/config.toml` in the current directory instead, which can be committed and shared with your team (see [Project-Scoped MCP Servers](#project-scoped-mcp-servers)). Header and environment variable values are stored verbatim, so reference secrets as `${VAR}` instead of pasting them into a committed project config (see [Example Configurations](#example-configurations)). `kigi mcp list` shows servers from both scopes, marking project-scoped ones with `(project)`.
`grok mcp remove` searches both scopes and exits 0 after removing the server. It exits 1 when the name is not found, or when the name is defined in both user and project scope — pass `--scope` to say which one to remove.
`kigi mcp remove` searches both scopes and exits 0 after removing the server. It exits 1 when the name is not found, or when the name is defined in both user and project scope — pass `--scope` to say which one to remove.
Breaking changes from earlier releases: `--env` now takes one `KEY=value` per flag (use `-e A=1 -e B=2`, not `--env A=1 B=2`), and server names may only contain letters, numbers, hyphens, and underscores.
@@ -142,9 +142,9 @@ url = "https://mcp.linear.app/mcp"
enabled = true
```
When a server exposes a native HTTP/SSE endpoint, prefer the `url` form over wrapping it in a stdio proxy such as `npx mcp-remote <url>`. Grok handles HTTP/SSE and OAuth directly, so the native form avoids an extra subprocess per session. It also registers Grok's own OAuth client with the provider.
When a server exposes a native HTTP/SSE endpoint, prefer the `url` form over wrapping it in a stdio proxy such as `npx mcp-remote <url>`. Kigi handles HTTP/SSE and OAuth directly, so the native form avoids an extra subprocess per session. It also registers Kigi's own OAuth client with the provider.
Grok walks from the current directory up to the git repo root, loading `.kigi/config.toml` at each level:
Kigi walks from the current directory up to the git repo root, loading `.kigi/config.toml` at each level:
| Location | Scope | Priority |
|----------|-------|----------|
@@ -154,7 +154,7 @@ Grok walks from the current directory up to the git repo root, loading `.kigi/co
If a project defines a server with the same name as a global one, the project version replaces it entirely (fields are not merged).
Project-scoped files contribute `[mcp_servers]`, `[plugins]`, and `[permission]` entries. Grok reads most other config sections only from `~/.kigi/config.toml`.
Project-scoped files contribute `[mcp_servers]`, `[plugins]`, and `[permission]` entries. Kigi reads most other config sections only from `~/.kigi/config.toml`.
---
@@ -169,7 +169,7 @@ MCP tools are namespaced with the server name to avoid collisions:
## Toggle Servers at Runtime
You can enable or disable MCP servers during a session without restarting Grok.
You can enable or disable MCP servers during a session without restarting Kigi.
### The /mcps Modal
@@ -198,24 +198,24 @@ The model has access to two built-in tools for working with MCP servers:
## Compatibility
Grok loads MCP server configurations from multiple sources for compatibility:
Kigi loads MCP server configurations from multiple sources for compatibility:
| Source | Format | Location | Configurable |
|--------|--------|----------|-------------|
| `config.toml` | Native Grok config | `~/.kigi/config.toml`, `.kigi/config.toml` | Always on |
| `config.toml` | Native Kigi config | `~/.kigi/config.toml`, `.kigi/config.toml` | Always on |
| `.claude.json` | Claude Code format | `~/.claude.json` | `[compat.claude] mcps` |
| `.cursor/mcp.json` | Cursor format | `~/.cursor/mcp.json`, `<project>/.cursor/mcp.json` | `[compat.cursor] mcps` |
| `.mcp.json` | MCP standard format | Project root (cwd to git root) | Loaded unless you have imported or dismissed the Claude import prompt (the import marker is set) |
All sources are merged in priority order: config.toml > Claude > Cursor > `.mcp.json`. Servers from higher-priority sources take precedence when names conflict.
The Claude and Cursor MCP sources are scanned by default. To disable scanning for a specific vendor, set `[compat.<vendor>] mcps = false` in `~/.kigi/config.toml` or the corresponding environment variable (`KIGI_CURSOR_MCPS_ENABLED`, `KIGI_CLAUDE_MCPS_ENABLED`). See [Configuration](05-configuration.md#harness-compatibility) for details. Use `grok inspect` to see which MCP servers were loaded and their vendor origin (`[cursor]`, `[claude]`).
The Claude and Cursor MCP sources are scanned by default. To disable scanning for a specific vendor, set `[compat.<vendor>] mcps = false` in `~/.kigi/config.toml` or the corresponding environment variable (`KIGI_CURSOR_MCPS_ENABLED`, `KIGI_CLAUDE_MCPS_ENABLED`). See [Configuration](05-configuration.md#harness-compatibility) for details. Use `kigi inspect` to see which MCP servers were loaded and their vendor origin (`[cursor]`, `[claude]`).
---
## MCP OAuth
For MCP servers that require OAuth authentication, Grok handles the credential flow automatically. When an MCP server requests OAuth credentials, Grok opens a browser-based authorization flow and stores the resulting tokens for future use.
For MCP servers that require OAuth authentication, Kigi handles the credential flow automatically. When an MCP server requests OAuth credentials, Kigi opens a browser-based authorization flow and stores the resulting tokens for future use.
---
@@ -225,7 +225,7 @@ Use the `url` form for hosted MCP servers and the `command` / `args` form for lo
### Native HTTP (hosted services)
You must authenticate OAuth-based MCP servers before you can use them. Grok stores the resulting tokens under `~/.kigi/mcp_credentials.json`. After you edit `config.toml`, press `r` in the `/mcps` modal to refresh the server list.
You must authenticate OAuth-based MCP servers before you can use them. Kigi stores the resulting tokens under `~/.kigi/mcp_credentials.json`. After you edit `config.toml`, press `r` in the `/mcps` modal to refresh the server list.
```toml
[mcp_servers.linear]
@@ -252,7 +252,7 @@ enabled = true
Authorization = "Bearer <token>"
```
To avoid putting secrets in the config file, reference an environment variable with `${VAR}` (or `${VAR:-default}`). Grok expands string fields in `[mcp_servers.*]``url`, `command`, `args`, and the values in `env` and `headers` — at load time:
To avoid putting secrets in the config file, reference an environment variable with `${VAR}` (or `${VAR:-default}`). Kigi expands string fields in `[mcp_servers.*]``url`, `command`, `args`, and the values in `env` and `headers` — at load time:
```toml
[mcp_servers.internal-tools]
@@ -285,7 +285,7 @@ tool_timeout_sec = 120
tool_timeouts = { slow_analysis = 300, quick_lookup = 10 }
```
On Windows, npm installs launchers like `npx`, `npm`, `pnpm`, and `yarn` as `.cmd` batch shims (there is no `npx.exe`). Grok resolves a bare `command` such as `npx` to its real launcher path on `PATH` (honoring `PATHEXT`) before spawning, so these work without manually wrapping them in `cmd /c`. A `command` given as an absolute path or one containing a path separator is used as-is.
On Windows, npm installs launchers like `npx`, `npm`, `pnpm`, and `yarn` as `.cmd` batch shims (there is no `npx.exe`). Kigi resolves a bare `command` such as `npx` to its real launcher path on `PATH` (honoring `PATHEXT`) before spawning, so these work without manually wrapping them in `cmd /c`. A `command` given as an absolute path or one containing a path separator is used as-is.
---
@@ -324,7 +324,7 @@ npx -y @modelcontextprotocol/server-filesystem /path
startup_timeout_sec = 30
```
For stdio servers, Grok captures the process's standard error to `~/.kigi/logs/mcp/<server>.stderr.log`, truncated on each launch. Check this file when a server starts but fails to handshake:
For stdio servers, Kigi captures the process's standard error to `~/.kigi/logs/mcp/<server>.stderr.log`, truncated on each launch. Check this file when a server starts but fails to handshake:
```bash
tail -f ~/.kigi/logs/mcp/filesystem.stderr.log
@@ -332,18 +332,18 @@ tail -f ~/.kigi/logs/mcp/filesystem.stderr.log
### Viewing Server Status
Use `grok inspect` to see all loaded MCP servers and their sources:
Use `kigi inspect` to see all loaded MCP servers and their sources:
```bash
grok inspect # Human-readable
grok inspect --json # Machine-readable
kigi inspect # Human-readable
kigi inspect --json # Machine-readable
```
### Debug Logging
```bash
RUST_LOG=debug KIGI_LOG_FILE=/tmp/grok.log grok
tail -f /tmp/grok.log
RUST_LOG=debug KIGI_LOG_FILE=/tmp/kigi.log kigi
tail -f /tmp/kigi.log
```
Look for log entries containing `mcp` to trace server startup, tool discovery, and tool call execution.
@@ -1,20 +1,20 @@
# Skills
Skills are reusable prompt packages that extend Grok with task-specific instructions. They let you capture a repeatable procedure once, instead of re-explaining it each session.
Skills are reusable prompt packages that extend Kigi with task-specific instructions. They let you capture a repeatable procedure once, instead of re-explaining it each session.
---
## What Are Skills?
A skill is a directory that contains a `SKILL.md` file. Its markdown body tells Grok how to handle a specific type of task: step-by-step instructions, conventions, and tool-usage patterns.
A skill is a directory that contains a `SKILL.md` file. Its markdown body tells Kigi how to handle a specific type of task: step-by-step instructions, conventions, and tool-usage patterns.
Use a skill for a repeatable procedure that's too specific for AGENTS.md but too long to retype. Grok activates a skill only when it applies to your current task.
Use a skill for a repeatable procedure that's too specific for AGENTS.md but too long to retype. Kigi activates a skill only when it applies to your current task.
---
## Skill Locations
Grok discovers skills from these directories, in priority order:
Kigi discovers skills from these directories, in priority order:
| Location | Scope | Priority | Notes |
|----------|-------|----------|-------|
@@ -26,13 +26,13 @@ Grok discovers skills from these directories, in priority order:
| `~/.cursor/skills/` | User | Lowest | Cursor compatibility (configurable) |
| `./.cursor/skills/` | Local / Repo | High | Project Cursor skills (when cursor compat skills are enabled) |
Grok deduplicates skills by name -- a higher-priority location overrides a lower one. Grok also scans `.agents/skills/` (and `commands/`) at each tier (alongside `.kigi/`) and walks every directory between your working directory and the repo root.
Kigi deduplicates skills by name -- a higher-priority location overrides a lower one. Kigi also scans `.agents/skills/` (and `commands/`) at each tier (alongside `.kigi/`) and walks every directory between your working directory and the repo root.
Flat `*.md` files under a `commands/` directory become user-invocable slash commands (filename stem = command name), matching Claude Code's legacy custom-command layout.
Skill and command discovery does **not** use `.gitignore`. Paths under known skill roots (`.kigi/`, `.agents/`, `.claude/`, `.cursor/`) always load when present on disk — teams often ignore `.claude/**` as local-only config while still expecting `/frontend`-style project commands to work. To hide a skill, use `[skills] ignore` in config (not repo ignore rules).
Grok scans the Claude and Cursor skill directories by default. To stop scanning a vendor, set its `skills` cell to `false` under `[compat.cursor]` or `[compat.claude]` in `~/.kigi/config.toml`, or set the `KIGI_CURSOR_SKILLS_ENABLED` or `KIGI_CLAUDE_SKILLS_ENABLED` environment variable to `false`. See [Configuration](05-configuration.md#harness-compatibility) for details. Grok always filters out known vendor-shipped default skills (such as Cursor's `shell`, `canvas`, and `statusline`), regardless of these settings.
Kigi scans the Claude and Cursor skill directories by default. To stop scanning a vendor, set its `skills` cell to `false` under `[compat.cursor]` or `[compat.claude]` in `~/.kigi/config.toml`, or set the `KIGI_CURSOR_SKILLS_ENABLED` or `KIGI_CLAUDE_SKILLS_ENABLED` environment variable to `false`. See [Configuration](05-configuration.md#harness-compatibility) for details. Kigi always filters out known vendor-shipped default skills (such as Cursor's `shell`, `canvas`, and `statusline`), regardless of these settings.
### Additional Skill Directories
@@ -45,7 +45,7 @@ ignore = ["~/my-team-skills/wip"] # Paths to exclude (hidden entirely)
disabled = ["wip-skill"] # Skill names to keep listed but inactive
```
Each entry in `paths` is a `SKILL.md` file or a directory that Grok walks recursively. `ignore` hides a skill completely; `disabled` keeps it in the list but excludes it from the system prompt and from invocation. `paths` and `ignore` take filesystem paths and support `~` expansion; `disabled` takes skill names.
Each entry in `paths` is a `SKILL.md` file or a directory that Kigi walks recursively. `ignore` hides a skill completely; `disabled` keeps it in the list but excludes it from the system prompt and from invocation. `paths` and `ignore` take filesystem paths and support `~` expansion; `disabled` takes skill names.
---
@@ -91,10 +91,10 @@ Review staged changes and create a commit with a clear, conventional message.
| Field | Description |
|-------|-------------|
| `name` | Skill identifier. Use lowercase letters, digits, and hyphens, up to 64 characters. Grok normalizes spaces and underscores to hyphens. If you omit `name`, Grok uses the skill's directory name. |
| `description` | What the skill does and when to use it. Grok reads this to decide whether to invoke the skill. If you omit it, Grok uses the first paragraph of the body. |
| `name` | Skill identifier. Use lowercase letters, digits, and hyphens, up to 64 characters. Kigi normalizes spaces and underscores to hyphens. If you omit `name`, Kigi uses the skill's directory name. |
| `description` | What the skill does and when to use it. Kigi reads this to decide whether to invoke the skill. If you omit it, Kigi uses the first paragraph of the body. |
Write a specific `description`. It determines when Grok invokes the skill automatically. Name the trigger phrases and use cases.
Write a specific `description`. It determines when Kigi invokes the skill automatically. Name the trigger phrases and use cases.
### Optional Frontmatter Fields
@@ -111,36 +111,36 @@ Multi-word frontmatter keys use kebab-case (single-word keys like `model` are wr
| `effort` | Reasoning-effort override. |
| `license` | License identifier (for example, `Apache-2.0`). |
| `compatibility` | Environment requirements (for example, `Requires git, docker, jq`). |
| `metadata` | Arbitrary string key-value pairs. Grok promotes `metadata.author` and `metadata.short-description` for display. |
| `metadata` | Arbitrary string key-value pairs. Kigi promotes `metadata.author` and `metadata.short-description` for display. |
---
## Creating Skills with /create-skill
The `/create-skill` command walks you through building a new skill interactively. Grok asks what you want, drafts the files, and writes them to disk.
The `/create-skill` command walks you through building a new skill interactively. Kigi asks what you want, drafts the files, and writes them to disk.
### How It Works
When you run `/create-skill`, Grok:
When you run `/create-skill`, Kigi:
1. **Gathers requirements.** Grok asks for the skill name, the scope to save it under, and a description of the workflow you want to capture. Use a name with lowercase letters, digits, and hyphens (264 characters, starting and ending with a letter or digit).
1. **Gathers requirements.** Kigi asks for the skill name, the scope to save it under, and a description of the workflow you want to capture. Use a name with lowercase letters, digits, and hyphens (264 characters, starting and ending with a letter or digit).
2. **Drafts the description.** Grok writes a `description` that states what the skill does, the phrases that trigger it, and the slash command name. You approve or edit the draft before continuing.
2. **Drafts the description.** Kigi writes a `description` that states what the skill does, the phrases that trigger it, and the slash command name. You approve or edit the draft before continuing.
3. **Creates the skill directory.** Grok creates the `<scope>/.kigi/skills/<name>/` directory, plus `scripts/` or `references/` subdirectories when the skill needs them.
3. **Creates the skill directory.** Kigi creates the `<scope>/.kigi/skills/<name>/` directory, plus `scripts/` or `references/` subdirectories when the skill needs them.
4. **Writes SKILL.md.** Grok writes the frontmatter (`name` and `description`) and a markdown body of instructions, along with any supporting files.
4. **Writes SKILL.md.** Kigi writes the frontmatter (`name` and `description`) and a markdown body of instructions, along with any supporting files.
5. **Verifies and confirms.** Grok reads the file back, confirms it wrote correctly, and tells you how to run the skill.
5. **Verifies and confirms.** Kigi reads the file back, confirms it wrote correctly, and tells you how to run the skill.
### Choosing a Scope
Grok asks where to save the skill:
Kigi asks where to save the skill:
- **Project** (`<repo_root>/.kigi/skills/<name>/`) -- available only in this repository and shareable with teammates through version control. Grok recommends this scope inside a git repository.
- **Project** (`<repo_root>/.kigi/skills/<name>/`) -- available only in this repository and shareable with teammates through version control. Kigi recommends this scope inside a git repository.
- **User** (`~/.kigi/skills/<name>/`) -- available across all your projects.
The new skill appears in the slash menu within a few seconds, because Grok reloads skills when files change on disk.
The new skill appears in the slash menu within a few seconds, because Kigi reloads skills when files change on disk.
---
@@ -161,11 +161,11 @@ Running a skill loads its instructions into the conversation and directs the mod
/commit fix the build
```
To browse your skills, type `/` to open the slash-command menu. Grok lists every built-in command and skill and filters them as you type. To list skills from the command line instead, run `grok inspect` (see [Viewing Skill Details](#viewing-skill-details)).
To browse your skills, type `/` to open the slash-command menu. Kigi lists every built-in command and skill and filters them as you type. To list skills from the command line instead, run `kigi inspect` (see [Viewing Skill Details](#viewing-skill-details)).
### Qualified Names
When a skill's name collides with another skill or a built-in command, Grok advertises a qualified name prefixed by the skill's scope -- `local:`, `repo:`, `user:`, or the plugin name. Use the qualified form to choose a specific skill:
When a skill's name collides with another skill or a built-in command, Kigi advertises a qualified name prefixed by the skill's scope -- `local:`, `repo:`, `user:`, or the plugin name. Use the qualified form to choose a specific skill:
```
/local:commit # The "commit" skill from ./.kigi/skills/
@@ -174,7 +174,7 @@ When a skill's name collides with another skill or a built-in command, Grok adve
### Automatic Invocation
Grok can invoke a skill on its own when it recognizes a relevant task. Grok matches your prompt against the skill's `description` and `when-to-use` fields, so write both to describe the triggering situation.
Kigi can invoke a skill on its own when it recognizes a relevant task. Kigi matches your prompt against the skill's `description` and `when-to-use` fields, so write both to describe the triggering situation.
For example, if a skill's description says "Use when the user wants to commit changes," then saying "commit my changes" can trigger that skill automatically. To require an explicit slash command and prevent automatic invocation, set `disable-model-invocation: true` in the frontmatter.
@@ -182,14 +182,14 @@ For example, if a skill's description says "Use when the user wants to commit ch
## Viewing Skill Details
Run `grok inspect` to see every skill Grok discovers, along with the rest of your configuration:
Run `kigi inspect` to see every skill Kigi discovers, along with the rest of your configuration:
```bash
grok inspect # Human-readable summary
grok inspect --json # Machine-readable report
kigi inspect # Human-readable summary
kigi inspect --json # Machine-readable report
```
In the human-readable output, the Skills section lists each skill's name and its source -- `project`, `user`, `bundled`, `config` (a `[skills].paths` entry), `server` (skills synced from the skill store in managed workspaces), or `plugin: <name>`. Grok tags any skill disabled via `[skills].disabled` or from a disabled vendor surface with `[disabled]`.
In the human-readable output, the Skills section lists each skill's name and its source -- `project`, `user`, `bundled`, `config` (a `[skills].paths` entry), `server` (skills synced from the skill store in managed workspaces), or `plugin: <name>`. Kigi tags any skill disabled via `[skills].disabled` or from a disabled vendor surface with `[disabled]`.
The report honors your `[skills]` config the same way a live session does: skills from `paths` are listed, skills under an `ignore` prefix are hidden, and skills named in `disabled` stay listed but tagged `[disabled]`.
@@ -199,9 +199,9 @@ The `--json` report includes the full detail for each skill: its `name`, `descri
## Bundled and Plugin Skills
Grok ships with built-in skills and extracts them to `~/.kigi/skills/` on startup -- among them `/create-skill`, `/help`, and `/check-work`. Bundled skills behave like user skills, and a same-named skill in a higher-priority location (local or repo) overrides the bundled copy; `grok inspect` labels the extracted copies `bundled` so they stay distinguishable from skills you authored yourself. (A plugin skill of the same name does not override it; it stays available under its qualified `plugin:name` form.)
Kigi ships with built-in skills and extracts them to `~/.kigi/skills/` on startup -- among them `/create-skill`, `/help`, and `/check-work`. Bundled skills behave like user skills, and a same-named skill in a higher-priority location (local or repo) overrides the bundled copy; `kigi inspect` labels the extracted copies `bundled` so they stay distinguishable from skills you authored yourself. (A plugin skill of the same name does not override it; it stays available under its qualified `plugin:name` form.)
Skills can also come from plugins. When you install a plugin that includes skills, they appear alongside your user and project skills. `grok inspect` labels each plugin-provided skill with its source as `plugin: <name>`.
Skills can also come from plugins. When you install a plugin that includes skills, they appear alongside your user and project skills. `kigi inspect` labels each plugin-provided skill with its source as `plugin: <name>`.
See the [Plugins guide](09-plugins.md) for more on installing plugins that provide skills.
@@ -211,7 +211,7 @@ See the [Plugins guide](09-plugins.md) for more on installing plugins that provi
1. **Write specific descriptions.** The description drives automatic invocation. "Create git commits" is too vague; "Create well-formatted git commits following conventional commit standards. Use when the user wants to commit changes or asks for /commit." works better.
2. **Include concrete steps.** Skills work best when they give Grok a clear, ordered procedure to follow.
2. **Include concrete steps.** Skills work best when they give Kigi a clear, ordered procedure to follow.
3. **Reference tools by name.** When a skill relies on specific tools (such as `run_terminal_command` or `search_replace`), name them so the model knows what to use.
@@ -15,7 +15,7 @@ A plugin is a directory that holds any combination of these components:
- **MCP servers** -- a `.mcp.json` file of server configurations
- **LSP servers** -- a `.lsp.json` file of language server configurations
If a plugin includes a `plugin.json` manifest, the manifest can override paths or add metadata; otherwise components load from the convention directories. The manifest is optional: without one, Grok discovers the components above from their standard directories.
If a plugin includes a `plugin.json` manifest, the manifest can override paths or add metadata; otherwise components load from the convention directories. The manifest is optional: without one, Kigi discovers the components above from their standard directories.
For example, a `team-tools` plugin might include a deploy skill, a code-review agent, pre-commit hooks, and a Linear MCP server. Install them together in one step.
@@ -28,25 +28,25 @@ Plugin hooks receive two environment variables beyond the standard ones set for
| `KIGI_PLUGIN_ROOT` | Absolute path to the plugin's installed directory. |
| `KIGI_PLUGIN_DATA` | Absolute path to the plugin's writable data directory, for plugin state, caches, and logs. |
Grok sets these values and overrides any value you declare for the same key in the hook JSON's `env` map. (Grok also sets the `CLAUDE_PLUGIN_ROOT` and `CLAUDE_PLUGIN_DATA` aliases for compatibility.) See the [Hooks guide](10-hooks.md) for every environment variable passed to hooks.
Kigi sets these values and overrides any value you declare for the same key in the hook JSON's `env` map. (Kigi also sets the `CLAUDE_PLUGIN_ROOT` and `CLAUDE_PLUGIN_DATA` aliases for compatibility.) See the [Hooks guide](10-hooks.md) for every environment variable passed to hooks.
---
## Plugin locations
Grok discovers plugins from these locations, in priority order:
Kigi discovers plugins from these locations, in priority order:
| Location | Scope | Trust |
|----------|-------|-------|
| `_meta.pluginDirs` (`session/new` / `session/load`) | Session -- loaded for that session only | Trusted automatically |
| `--plugin-dir` (CLI flag, `grok agent`) | Process -- loaded for that agent process only | Trusted automatically |
| `--plugin-dir` (CLI flag, `kigi agent`) | Process -- loaded for that agent process only | Trusted automatically |
| `.kigi/plugins/` | Project -- shared with the team through version control | Requires trust |
| `~/.kigi/plugins/` | User -- personal plugins for every project | Trusted automatically |
| `[plugins].paths` (config) | Custom directories you add in `config.toml` | Depends on location |
Grok also reads the `.claude/plugins/` equivalents for compatibility. When two plugins share a name, the higher-priority location wins.
Kigi also reads the `.claude/plugins/` equivalents for compatibility. When two plugins share a name, the higher-priority location wins.
The Agent SDKs load per-session plugins through `GrokOptions.plugins`, which arrives as `_meta.pluginDirs` on `session/new` and `session/load`; because the caller controls the directory, these plugins are always trusted -- their hooks and MCP servers activate without a prompt, and they never persist beyond the session. The `--plugin-dir` flag is the process-wide equivalent for direct CLI use (repeatable: `grok agent --no-leader --plugin-dir A --plugin-dir B stdio`); it applies to dedicated agent processes only and is ignored in leader mode (the shared leader discovers its own plugins).
The Agent SDKs load per-session plugins through `KigiOptions.plugins`, which arrives as `_meta.pluginDirs` on `session/new` and `session/load`; because the caller controls the directory, these plugins are always trusted -- their hooks and MCP servers activate without a prompt, and they never persist beyond the session. The `--plugin-dir` flag is the process-wide equivalent for direct CLI use (repeatable: `kigi agent --no-leader --plugin-dir A --plugin-dir B stdio`); it applies to dedicated agent processes only and is ignored in leader mode (the shared leader discovers its own plugins).
---
@@ -88,18 +88,18 @@ Use these keys in the Plugins tab:
### Plugin commands
```bash
grok plugin list [--json] [--available] # List installed plugins (--available requires --json)
grok plugin install <source> --trust # Git URL, GitHub shorthand (user/repo), or local path
grok plugin uninstall <name> [--confirm] [--keep-data] # Aliases: rm, remove
grok plugin update [<name>] # Omit the name to update all plugins
grok plugin enable <name>
grok plugin disable <name>
grok plugin details <name> # Show the plugin's component inventory
grok plugin validate [<path>] # Validate plugin.json (default: current directory)
grok plugin tag [<path>] [--push] [--force] [--dry-run] # Tag a release from the manifest version
kigi plugin list [--json] [--available] # List installed plugins (--available requires --json)
kigi plugin install <source> --trust # Git URL, GitHub shorthand (user/repo), or local path
kigi plugin uninstall <name> [--confirm] [--keep-data] # Aliases: rm, remove
kigi plugin update [<name>] # Omit the name to update all plugins
kigi plugin enable <name>
kigi plugin disable <name>
kigi plugin details <name> # Show the plugin's component inventory
kigi plugin validate [<path>] # Validate plugin.json (default: current directory)
kigi plugin tag [<path>] [--push] [--force] [--dry-run] # Tag a release from the manifest version
```
Run `grok plugin install <source>` without `--trust` and Grok prints the source and warns that installing will activate the plugin's hooks, MCP servers, and skills, then stops without installing. Add `--trust` to install it.
Run `kigi plugin install <source>` without `--trust` and Kigi prints the source and warns that installing will activate the plugin's hooks, MCP servers, and skills, then stops without installing. Add `--trust` to install it.
The `<source>` argument accepts:
@@ -124,21 +124,21 @@ disable_plugins = true
Enabling a plugin loads its skills, slash commands, and agents. Trust is separate and controls whether a plugin's code runs: even for an enabled plugin, its hooks, MCP servers, and LSP servers stay inactive until you trust it. This prevents an untrusted repository from running code on your machine.
Grok trusts plugins from `~/.kigi/plugins/` automatically. Project plugins in `.kigi/plugins/` require explicit trust. To trust a plugin, install it with `--trust`:
Kigi trusts plugins from `~/.kigi/plugins/` automatically. Project plugins in `.kigi/plugins/` require explicit trust. To trust a plugin, install it with `--trust`:
```bash
grok plugin install <source> --trust
kigi plugin install <source> --trust
```
---
## Inspect plugins
Run `grok inspect` to see every discovered plugin and what it provides:
Run `kigi inspect` to see every discovered plugin and what it provides:
```bash
grok inspect # Show plugins with their skills, agents, hooks, and MCP servers
grok inspect --json # Emit machine-readable JSON
kigi inspect # Show plugins with their skills, agents, hooks, and MCP servers
kigi inspect --json # Emit machine-readable JSON
```
Plugin-provided components appear in their sections (Skills, Agents, MCP Servers, and so on) with a `plugin: <name>` label, so you can see where each component originates.
@@ -1,12 +1,12 @@
# Hooks
Hooks let you run a script or send an HTTP request at key moments in a Grok session. Use them to automate tasks, enforce safety checks, log activity, send notifications, and integrate your own tools.
Hooks let you run a script or send an HTTP request at key moments in a Kigi session. Use them to automate tasks, enforce safety checks, log activity, send notifications, and integrate your own tools.
---
## What Are Hooks?
A hook is a shell command or HTTP endpoint that Grok calls when a specific lifecycle event occurs. Hooks can:
A hook is a shell command or HTTP endpoint that Kigi calls when a specific lifecycle event occurs. Hooks can:
- **Block actions** -- A `PreToolUse` hook can deny a dangerous command before it runs.
- **React to events** -- A `PostToolUse` hook can log every tool execution to a file.
@@ -41,7 +41,7 @@ A hook is a shell command or HTTP endpoint that Grok calls when a specific lifec
"SessionStart": [
{
"hooks": [
{ "type": "command", "command": "echo 'Grok session started in '$(pwd)" }
{ "type": "command", "command": "echo 'Kigi session started in '$(pwd)" }
]
}
]
@@ -49,7 +49,7 @@ A hook is a shell command or HTTP endpoint that Grok calls when a specific lifec
}
```
3. Start (or restart) a Grok session. The hook runs automatically on `SessionStart`.
3. Start (or restart) a Kigi session. The hook runs automatically on `SessionStart`.
4. Press `Ctrl+L` on nonVS Code family terminals (or run `/hooks` anywhere — preferred on VS Code family) and check the Hooks tab to confirm it loaded.
@@ -100,7 +100,7 @@ Because hooks are unified under folder-trust, a `--trust` / `/hooks-trust` grant
### Cursor Hook Compatibility
Grok accepts Cursor's camelCase hook event names, so `~/.cursor/hooks.json` loads unchanged:
Kigi accepts Cursor's camelCase hook event names, so `~/.cursor/hooks.json` loads unchanged:
| Cursor event | Maps to |
|---|---|
@@ -145,7 +145,7 @@ Each `.json` file can define hooks for multiple events:
### Key Fields
- **Event name** (top-level key): any event listed in [Hook Events](#hook-events). Grok skips unrecognized event names so a shared Claude or Cursor settings file still loads.
- **Event name** (top-level key): any event listed in [Hook Events](#hook-events). Kigi skips unrecognized event names so a shared Claude or Cursor settings file still loads.
- **matcher** (optional): A regular expression that selects which invocations trigger the hook. It applies to the tool events — `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, and `PermissionDenied` — where it tests the tool name, and to `Notification`, where it tests the notification type. The lifecycle events (`SessionStart`, `SessionEnd`, `Stop`, `UserPromptSubmit`) reject a matcher; other events ignore it. An empty or omitted matcher matches everything. The matcher tests the real tool name; MCP calls routed through the internal `use_tool` dispatcher appear as the qualified `server__tool` name (e.g. `linear__save_issue`), so match on that, not the dispatcher name.
- **type**: `"command"` (run a script or shell one-liner) or `"http"` (POST the event to a URL).
- **command**: Path to executable (relative to the JSON file) or inline shell command.
@@ -153,7 +153,7 @@ Each `.json` file can define hooks for multiple events:
### Tool Name Aliases
In a `matcher`, Grok maps Claude-style tool names to its own so hooks migrated from Claude fire correctly. Common aliases include:
In a `matcher`, Kigi maps Claude-style tool names to its own so hooks migrated from Claude fire correctly. Common aliases include:
- `Bash` → `run_terminal_command`
- `Read` → `read_file`
@@ -206,7 +206,7 @@ For events like `SessionStart` or `PostToolUse`, stdout is ignored. Just exit 0
### Environment Variables
Grok sets several environment variables on every hook process. These are useful when writing context-aware or plugin-aware hook scripts.
Kigi sets several environment variables on every hook process. These are useful when writing context-aware or plugin-aware hook scripts.
#### Runner-injected variables (always available)
@@ -216,7 +216,7 @@ These variables are set by the hook runner for **every** hook:
|-----------------------|-------------|
| `KIGI_HOOK_EVENT` | The name of the event that triggered the hook (e.g. `pre_tool_use`, `session_start`, `post_tool_use`, `session_end`, `stop`, `notification`). |
| `KIGI_HOOK_NAME` | The configured name of this specific hook (includes the plugin prefix for plugin-provided hooks). |
| `KIGI_SESSION_ID` | The unique identifier of the current Grok session. |
| `KIGI_SESSION_ID` | The unique identifier of the current Kigi session. |
| `KIGI_WORKSPACE_ROOT` | Absolute path to the root of the current workspace. |
| `CLAUDE_PROJECT_DIR` | Absolute path to the workspace root. A Claude Code-compatible alias for `KIGI_WORKSPACE_ROOT`, set for every hook. |
@@ -224,7 +224,7 @@ These variables are **reserved**. Any values you attempt to set for them via the
#### Plugin hook variables
When a hook originates from a plugin, Grok additionally injects the following variables:
When a hook originates from a plugin, Kigi additionally injects the following variables:
| Variable | Description |
|----------------------|-------------|
@@ -261,7 +261,7 @@ Both `command` and `url` support `${VAR}` and `$VAR` expansion. See the custom-h
Instead of a local script, call a remote endpoint:
```json
{ "type": "http", "url": "https://hooks.example.com/grok-event", "timeout": 15 }
{ "type": "http", "url": "https://hooks.example.com/kigi-event", "timeout": 15 }
```
The full event envelope is POSTed as JSON.
@@ -308,7 +308,7 @@ Enable or disable an individual hook at runtime by pressing `Space` in the Hooks
### Mid-Session Reload
Press `r` in the Hooks tab to reload all hooks from disk. Grok re-reads every hook source, so this picks up changes you made to hook files during the session.
Press `r` in the Hooks tab to reload all hooks from disk. Kigi re-reads every hook source, so this picks up changes you made to hook files during the session.
---
@@ -378,4 +378,4 @@ echo '{"decision": "allow"}'
- **Hook not running?** Press `Ctrl+L` on nonVS Code family (or run `/hooks` anywhere) to see if it is loaded and matched.
- **Project hooks ignored?** The folder may be untrusted. Run `/hooks-trust` (or relaunch with `--trust`).
- **Script not found?** Check the path is relative to the `.json` file and executable (`chmod +x`).
- **See errors?** Capture logs by launching with `RUST_LOG=debug KIGI_LOG_FILE=/tmp/grok.log grok`, then check `/tmp/grok.log`.
- **See errors?** Capture logs by launching with `RUST_LOG=debug KIGI_LOG_FILE=/tmp/kigi.log kigi`, then check `/tmp/kigi.log`.
@@ -1,17 +1,17 @@
# Custom Models
Grok connects to custom model endpoints for alternative providers, self-hosted models, and overriding built-in settings. This guide explains how to select models, configure endpoints, and integrate third-party providers.
Kigi connects to custom model endpoints for alternative providers, self-hosted models, and overriding built-in settings. This guide explains how to select models, configure endpoints, and integrate third-party providers.
---
## Default Models
By default, Grok uses models hosted by SpaceXAI, and new sessions start with `grok-build`. Default models require no configuration. Authenticate with `grok login` or an API key, then start a session.
By default, Kigi uses models hosted by SpaceXAI, and new sessions start with `kigi`. Default models require no configuration. Authenticate with `kigi login` or an API key, then start a session.
List all available models:
```bash
grok models
kigi models
```
---
@@ -21,7 +21,7 @@ grok models
### CLI Flag
```bash
grok -p "Hello" -m grok-build
kigi -p "Hello" -m kigi
```
### Slash Command
@@ -29,13 +29,13 @@ grok -p "Hello" -m grok-build
In the TUI, switch models during a session:
```
/model grok-build
/model kigi
```
Or use the alias:
```
/m grok-build
/m kigi
```
### Model Picker (Ctrl+M)
@@ -48,14 +48,14 @@ Set a persistent default in `~/.kigi/config.toml`:
```toml
[models]
default = "grok-build"
default = "kigi"
```
---
## Supported API Backends
Grok supports three API backends. Set `api_backend` in your `[model.*]` config to choose which protocol the model uses:
Kigi supports three API backends. Set `api_backend` in your `[model.*]` config to choose which protocol the model uses:
| Value | API | Default |
|-------|-----|---------|
@@ -63,9 +63,9 @@ Grok supports three API backends. Set `api_backend` in your `[model.*]` config t
| `"responses"` | OpenAI Responses (`/v1/responses`) | |
| `"messages"` | Anthropic Messages (`/v1/messages`) | |
When you omit `api_backend`, Grok uses `chat_completions`.
When you omit `api_backend`, Kigi uses `chat_completions`.
To send provider-specific authentication or version headers -- for example, Anthropic's `x-api-key` -- use the `extra_headers` field described below. Grok sends those headers verbatim with every request to the endpoint.
To send provider-specific authentication or version headers -- for example, Anthropic's `x-api-key` -- use the `extra_headers` field described below. Kigi sends those headers verbatim with every request to the endpoint.
---
@@ -91,16 +91,16 @@ extra_headers = { "x-api-key" = "sk-..." } # Extra request headers, sent verbati
### Credential Resolution
Grok resolves the API key in this order:
Kigi resolves the API key in this order:
1. The `api_key` field in the model config
2. The environment variable(s) named by `env_key` — a single string or an array of names. The first set, non-empty value wins (for example `env_key = ["ANTHROPIC_AUTH_TOKEN", "LC_ANTHROPIC_AUTH_TOKEN"]` for SSH `LC_*` forwarding)
3. Your signed-in session token (from `grok login`), for a model with no `api_key`/`env_key` of its own
4. The `XAI_API_KEY` environment variable (global fallback; Grok also accepts `KIGI_CODE_XAI_API_KEY` for backward compatibility)
3. Your signed-in session token (from `kigi login`), for a model with no `api_key`/`env_key` of its own
4. The `XAI_API_KEY` environment variable (global fallback; Kigi also accepts `KIGI_CODE_XAI_API_KEY` for backward compatibility)
### Context Window
The `context_window` value tells Grok when to trigger auto-compaction. When you override a known model, Grok inherits that model's context window. When you define a new model and omit `context_window`, Grok defaults to 200,000 tokens, so set it explicitly to match your provider.
The `context_window` value tells Kigi when to trigger auto-compaction. When you override a known model, Kigi inherits that model's context window. When you define a new model and omit `context_window`, Kigi defaults to 200,000 tokens, so set it explicitly to match your provider.
### Global Default Headers
@@ -148,7 +148,7 @@ temperature = 0.5
api_key = "sk-custom"
```
When you override a built-in model, Grok starts with the default configuration (including the correct `base_url`), then applies only the fields you specify. Unspecified fields inherit from the default.
When you override a built-in model, Kigi starts with the default configuration (including the correct `base_url`), then applies only the fields you specify. Unspecified fields inherit from the default.
### Priority Order
@@ -174,7 +174,7 @@ context_window = 200000
extra_headers = { "x-api-key" = "sk-ant-...", "anthropic-version" = "2023-06-01" }
```
The `messages` backend uses the Anthropic Messages protocol. Anthropic authenticates with an `x-api-key` header rather than `Authorization: Bearer`, so pass your key through `extra_headers`, which Grok sends verbatim.
The `messages` backend uses the Anthropic Messages protocol. Anthropic authenticates with an `x-api-key` header rather than `Authorization: Bearer`, so pass your key through `extra_headers`, which Kigi sends verbatim.
### OpenAI (Chat Completions)
@@ -240,14 +240,14 @@ temperature = 0.8
## Custom Models Endpoint
Point Grok at a custom OpenAI-compatible `/v1/models` endpoint instead of the default. Use this when your models sit behind a corporate gateway or a self-hosted inference service.
Point Kigi at a custom OpenAI-compatible `/v1/models` endpoint instead of the default. Use this when your models sit behind a corporate gateway or a self-hosted inference service.
### Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| `KIGI_MODELS_BASE_URL` | Yes | Base URL for inference. Grok fetches the model list from `{base_url}/models`. |
| `XAI_API_KEY` | Yes | API key sent as `Authorization: Bearer`. Grok also accepts `KIGI_CODE_XAI_API_KEY`. |
| `KIGI_MODELS_BASE_URL` | Yes | Base URL for inference. Kigi fetches the model list from `{base_url}/models`. |
| `XAI_API_KEY` | Yes | API key sent as `Authorization: Bearer`. Kigi also accepts `KIGI_CODE_XAI_API_KEY`. |
| `KIGI_MODELS_LIST_URL` | No | Override the model-list URL when it differs from `{base_url}/models`. |
### Setup
@@ -255,7 +255,7 @@ Point Grok at a custom OpenAI-compatible `/v1/models` endpoint instead of the de
```bash
export KIGI_MODELS_BASE_URL="https://api.acme.com/v1"
export XAI_API_KEY="xai-..."
grok
kigi
```
### Config File Alternative
@@ -269,11 +269,11 @@ models_base_url = "https://api.acme.com/v1"
api_key = "my-api-key"
```
When you use `[endpoints]` with partial model overrides, Grok inherits the `base_url` from the endpoints config, so you do not need to specify it in each `[model.*]` section.
When you use `[endpoints]` with partial model overrides, Kigi inherits the `base_url` from the endpoints config, so you do not need to specify it in each `[model.*]` section.
### Auth Behavior
When you set `models_base_url`, Grok uses API key auth (`Authorization: Bearer`) instead of session auth. You do not need `grok login` -- the API key is enough.
When you set `models_base_url`, Kigi uses API key auth (`Authorization: Bearer`) instead of session auth. You do not need `kigi login` -- the API key is enough.
---
@@ -281,13 +281,13 @@ When you set `models_base_url`, Grok uses API key auth (`Authorization: Bearer`)
```bash
# List available models (including custom)
grok models
kigi models
# Use in the TUI via slash command
/model my-model
# Use in headless mode
grok -p "Hello" -m my-model
kigi -p "Hello" -m my-model
# Set as default in config.toml:
[models]
@@ -310,12 +310,12 @@ auth_provider_label = "Acme Corp"
auth_token_ttl = 3600
[models]
default = "company-grok"
default = "company-kigi"
[model.company-grok]
model = "grok-build"
base_url = "https://grok-proxy.acme.com/"
name = "Grok Build Latest (Proxy)"
[model.company-kigi]
model = "kigi"
base_url = "https://kigi-proxy.acme.com/"
name = "Kigi Latest (Proxy)"
context_window = 128000
[features]
@@ -330,7 +330,7 @@ telemetry = false
```bash
# List available models
grok models
kigi models
# Check config.toml for typos in [model.*] sections
```
@@ -347,8 +347,8 @@ curl -s https://api.example.com/v1/models \
### Debug Logging
```bash
RUST_LOG=debug KIGI_LOG_FILE=/tmp/grok.log grok
tail -f /tmp/grok.log
RUST_LOG=debug KIGI_LOG_FILE=/tmp/kigi.log kigi
tail -f /tmp/kigi.log
```
Look for log entries containing `model` or `sampling` to trace model selection and API calls.
@@ -1,20 +1,20 @@
# Project Rules (AGENTS.md)
Project rules let you configure Grok per project or directory. By placing an AGENTS.md file in your repository, you can set coding conventions, build instructions, style guides, and any other instructions that Grok should follow when working in that codebase.
Project rules let you configure Kigi per project or directory. By placing an AGENTS.md file in your repository, you can set coding conventions, build instructions, style guides, and any other instructions that Kigi should follow when working in that codebase.
---
## What Are Project Rules?
Project rules are Markdown files that Grok reads and adds to its context. Grok follows their content for every interaction in that tree.
Project rules are Markdown files that Kigi reads and adds to its context. Kigi follows their content for every interaction in that tree.
This is the primary mechanism for teaching Grok about your project's conventions, so you need not restate them each session.
This is the primary mechanism for teaching Kigi about your project's conventions, so you need not restate them each session.
---
## Supported File Names
Grok checks for these filenames (in this order) within each directory:
Kigi checks for these filenames (in this order) within each directory:
- `Agents.md`
- `Claude.md`
@@ -23,11 +23,11 @@ Grok checks for these filenames (in this order) within each directory:
- `AGENT.md`
- `AGENTS.md`
Grok loads every matching file in a directory, so a folder that contains both `AGENTS.md` and `CLAUDE.md` contributes both. On case-insensitive filesystems, names that resolve to the same file (such as `Agents.md` and `AGENTS.md`) are deduplicated and counted once. `Claude.md`, `CLAUDE.md`, and `CLAUDE.local.md` are supported for compatibility with Claude Code workflows. When Claude compatibility is enabled (the default), Grok also scans your home-level `~/.claude/` directory for these filenames and, at each directory level, checks `.claude/CLAUDE.md` and `.claude/CLAUDE.local.md` -- the locations Claude Code uses for project memory. With Cursor compatibility enabled, the home-level `~/.cursor/` directory is scanned the same way.
Kigi loads every matching file in a directory, so a folder that contains both `AGENTS.md` and `CLAUDE.md` contributes both. On case-insensitive filesystems, names that resolve to the same file (such as `Agents.md` and `AGENTS.md`) are deduplicated and counted once. `Claude.md`, `CLAUDE.md`, and `CLAUDE.local.md` are supported for compatibility with Claude Code workflows. When Claude compatibility is enabled (the default), Kigi also scans your home-level `~/.claude/` directory for these filenames and, at each directory level, checks `.claude/CLAUDE.md` and `.claude/CLAUDE.local.md` -- the locations Claude Code uses for project memory. With Cursor compatibility enabled, the home-level `~/.cursor/` directory is scanned the same way.
### Rules Directories
In addition to AGENTS.md files, Grok scans for `*.md` files in rules directories at each level (`<dir>`) from the repo root to the current working directory:
In addition to AGENTS.md files, Kigi scans for `*.md` files in rules directories at each level (`<dir>`) from the repo root to the current working directory:
| Location | Notes |
|----------|-------|
@@ -35,13 +35,13 @@ In addition to AGENTS.md files, Grok scans for `*.md` files in rules directories
| `<dir>/.claude/rules/` | Claude compatibility (configurable) |
| `<dir>/.cursor/rules/` | Cursor compatibility (configurable) |
Grok scans the Claude and Cursor rules directories by default. To disable scanning for a specific vendor, set its cell in the `[compat]` config section or the corresponding environment variable. See [Configuration](05-configuration.md#harness-compatibility) for details.
Kigi scans the Claude and Cursor rules directories by default. To disable scanning for a specific vendor, set its cell in the `[compat]` config section or the corresponding environment variable. See [Configuration](05-configuration.md#harness-compatibility) for details.
---
## How Discovery Works
Grok scans for project rules in this order:
Kigi scans for project rules in this order:
1. **Global rules**: `~/.kigi/` (applies to all projects)
2. **Repo rules**: If inside a git repo, every directory from the repo root down to the current working directory (inclusive)
@@ -60,16 +60,16 @@ Given this project structure:
AGENTS.md # "Use CSS modules for styling."
```
When Grok runs in `~/projects/my-app/src/components/`, it loads all three files. The instructions accumulate, so Grok sees all of them.
When Kigi runs in `~/projects/my-app/src/components/`, it loads all three files. The instructions accumulate, so Kigi sees all of them.
### Deeper Files Take Precedence
Grok orders the files from the repo root to the current working directory, so files in deeper directories appear later in its context and take precedence when instructions conflict. In the example above, if the root says "Use styled-components" but `components/AGENTS.md` says "Use CSS modules", the CSS modules instruction wins because it appears later.
Kigi orders the files from the repo root to the current working directory, so files in deeper directories appear later in its context and take precedence when instructions conflict. In the example above, if the root says "Use styled-components" but `components/AGENTS.md` says "Use CSS modules", the CSS modules instruction wins because it appears later.
### Auto-Loading Behavior
- Grok loads the files from the repo root to the current working directory automatically at session start.
- When Grok reads, lists, or edits files in directories outside that initial set, it detects any project instruction files there, notes their paths, and reads them when they apply to the task.
- Kigi loads the files from the repo root to the current working directory automatically at session start.
- When Kigi reads, lists, or edits files in directories outside that initial set, it detects any project instruction files there, notes their paths, and reads them when they apply to the task.
---
@@ -155,18 +155,18 @@ my-monorepo/
To add rules for a single session without editing files, pass `--rules` (alias `--append-system-prompt`):
```bash
grok --rules "Always use TypeScript. Prefer functional components."
kigi --rules "Always use TypeScript. Prefer functional components."
```
Grok appends this text to the session's system prompt. Use it for session-specific customization.
Kigi appends this text to the session's system prompt. Use it for session-specific customization.
To replace the system prompt entirely, pass `--system-prompt-override` (alias `--system-prompt`). Grok uses the text verbatim and skips both the default system prompt and `--rules`. (Text passed with `--rules`, by contrast, is wrapped in a `<human_rules>` block and appended to the default prompt.)
To replace the system prompt entirely, pass `--system-prompt-override` (alias `--system-prompt`). Kigi uses the text verbatim and skips both the default system prompt and `--rules`. (Text passed with `--rules`, by contrast, is wrapped in a `<human_rules>` block and appended to the default prompt.)
---
## File Size
Grok loads each project instruction file in full; there is no character cap and no truncation. Even so, keep instructions concise and focused. Shorter, specific rules are easier for Grok to follow than long ones, and every file you load consumes context.
Kigi loads each project instruction file in full; there is no character cap and no truncation. Even so, keep instructions concise and focused. Shorter, specific rules are easier for Kigi to follow than long ones, and every file you load consumes context.
---
@@ -179,7 +179,7 @@ Files ignored by `.gitignore` are skipped during discovery. To keep personal ove
CLAUDE.local.md
```
As top-level instruction files, Grok discovers only the recognized filenames listed under [Supported File Names](#supported-file-names) — not custom names such as `AGENTS.local.md` or `notes.md`. (Inside a rules directory such as `.kigi/rules/`, every `*.md` file is loaded regardless of name.)
As top-level instruction files, Kigi discovers only the recognized filenames listed under [Supported File Names](#supported-file-names) — not custom names such as `AGENTS.local.md` or `notes.md`. (Inside a rules directory such as `.kigi/rules/`, every `*.md` file is loaded regardless of name.)
---
@@ -202,13 +202,13 @@ These are all optional. See the respective guides for details on each.
## Inspecting Loaded Rules
Use `grok inspect` to see all loaded project instructions:
Use `kigi inspect` to see all loaded project instructions:
```bash
grok inspect
kigi inspect
```
This shows each project instruction file it finds, with its path and approximate token count. Use it to confirm Grok picks up your rules.
This shows each project instruction file it finds, with its path and approximate token count. Use it to confirm Kigi picks up your rules.
---
@@ -1,12 +1,12 @@
# Cross-Session Memory
Memory lets Grok recall facts, decisions, and patterns from earlier sessions. Grok indexes the information you save and searches it automatically, so a new session can reuse relevant context.
Memory lets Kigi recall facts, decisions, and patterns from earlier sessions. Kigi indexes the information you save and searches it automatically, so a new session can reuse relevant context.
---
## What Is Memory?
Without memory, each Grok session starts fresh: the model knows nothing about previous sessions. When you enable memory, Grok can:
Without memory, each Kigi session starts fresh: the model knows nothing about previous sessions. When you enable memory, Kigi can:
- Recall project conventions you explained before.
- Reuse debugging steps that worked.
@@ -22,14 +22,14 @@ Memory is experimental and disabled by default.
### Per-Session Flag
```bash
grok --experimental-memory
kigi --experimental-memory
```
### Environment Variable
```bash
export KIGI_MEMORY=1
grok
kigi
```
### Config File (Persistent)
@@ -45,7 +45,7 @@ enabled = true
To disable memory even when other settings enable it:
```bash
grok --no-memory
kigi --no-memory
```
Or:
@@ -89,7 +89,7 @@ Memory is stored as Markdown files under `~/.kigi/memory/`:
| `~/.kigi/memory/<project-slug>-<hash8>/MEMORY.md` | Workspace | Project-specific conventions and context |
| `~/.kigi/memory/<project-slug>-<hash8>/sessions/` | Sessions | Per-session summaries and logs |
Grok suffixes each workspace directory with a short hash of the repository's identity. The identity is the `origin` remote in `org/repo` form when the directory is a Git repository with an `origin` remote, or the directory path otherwise. Because clones and worktrees of the same repository share an `origin` remote, they also share one memory directory.
Kigi suffixes each workspace directory with a short hash of the repository's identity. The identity is the `origin` remote in `org/repo` form when the directory is a Git repository with an `origin` remote, or the directory path otherwise. Because clones and worktrees of the same repository share an `origin` remote, they also share one memory directory.
An SQLite index supports hybrid search across all memory files:
- **FTS5** provides full-text search for keyword matching.
@@ -99,13 +99,13 @@ An SQLite index supports hybrid search across all memory files:
## Automatic Saves
When a session ends, Grok saves a structured metadata summary to that session's daily log. The summary contains:
When a session ends, Kigi saves a structured metadata summary to that session's daily log. The summary contains:
- Message counts (user, assistant, and tool results).
- Topics: the first few substantive user prompts from the session, up to five.
- The session date and time (UTC).
Grok builds the summary from conversation metadata without an LLM call, without added latency. Grok skips the save for trivial sessions -- those with fewer than three substantive prompts, or fewer than 50 bytes of user text.
Kigi builds the summary from conversation metadata without an LLM call, without added latency. Kigi skips the save for trivial sessions -- those with fewer than three substantive prompts, or fewer than 50 bytes of user text.
The summary does not record tool usage, file paths, or shell commands. The session ID forms part of the log filename. To turn automatic saves off, set `session.save_on_end = false`. For richer capture of decisions, patterns, and reasoning, use `/flush`.
@@ -132,13 +132,13 @@ Use `/flush` when you want to preserve important context:
### Remember
Ask Grok to remember something, and it appends the note to a `MEMORY.md` file -- the workspace file for project-specific items, or the global `~/.kigi/memory/MEMORY.md` for cross-project preferences:
Ask Kigi to remember something, and it appends the note to a `MEMORY.md` file -- the workspace file for project-specific items, or the global `~/.kigi/memory/MEMORY.md` for cross-project preferences:
```
> remember to always open PR links after pushing
```
Grok records entries as durable statements under organized headings, such as `## Preferences`, `## Project Context`, or `## Debugging`. The file watcher reindexes the change on the next memory search, so the new entry is searchable within the current session.
Kigi records entries as durable statements under organized headings, such as `## Preferences`, `## Project Context`, or `## Debugging`. The file watcher reindexes the change on the next memory search, so the new entry is searchable within the current session.
You can also save a note directly with the `/remember` command:
@@ -146,11 +146,11 @@ You can also save a note directly with the `/remember` command:
/remember always open PR links after pushing
```
Run `/remember` with no text to enter remember mode, where the next line you type becomes the note. Either way, Grok opens a review panel showing the note (with an optional rewritten version you can toggle with `Tab`); the note is written only after you confirm. On save, Grok shows `Memory saved to ~/.kigi/memory/MEMORY.md`.
Run `/remember` with no text to enter remember mode, where the next line you type becomes the note. Either way, Kigi opens a review panel showing the note (with an optional rewritten version you can toggle with `Tab`); the note is written only after you confirm. On save, Kigi shows `Memory saved to ~/.kigi/memory/MEMORY.md`.
### Forget
Ask Grok to forget something, and it finds and removes the matching entry:
Ask Kigi to forget something, and it finds and removes the matching entry:
```
> forget the snake_case convention
@@ -160,13 +160,13 @@ Forget is best-effort: the model searches memory and removes entries that match.
### Recall
Ask what Grok remembers:
Ask what Kigi remembers:
```
> what do you remember?
```
Grok searches across all memory files and summarizes what it knows, grouped by source: global preferences, project-specific knowledge, and session history. Use `/memory` to browse the raw files.
Kigi searches across all memory files and summarizes what it knows, grouped by source: global preferences, project-specific knowledge, and session history. Use `/memory` to browse the raw files.
### Direct Editing
@@ -212,13 +212,13 @@ You can also open `/memory` from the command palette.
## Memory Notifications
When you save a note with `/remember`, Grok confirms in the scrollback:
When you save a note with `/remember`, Kigi confirms in the scrollback:
```
Memory saved to ~/.kigi/memory/MEMORY.md
```
Background saves — flush, dream, and session-end — run silently and do not post a scrollback message. Use `/memory` at any time to browse what Grok has stored.
Background saves — flush, dream, and session-end — run silently and do not post a scrollback message. Use `/memory` at any time to browse what Kigi has stored.
---
@@ -234,7 +234,7 @@ Dream reorganizes individual session logs and memory entries into a coherent, de
### Auto-Dream
Dream also runs automatically. By default, Grok checks the consolidation gates when a session ends and runs Dream once enough time has passed and enough sessions have accumulated:
Dream also runs automatically. By default, Kigi checks the consolidation gates when a session ends and runs Dream once enough time has passed and enough sessions have accumulated:
```toml
[memory.dream]
@@ -251,7 +251,7 @@ min_sessions = 3 # Minimum sessions since the last consolidation
### First-Turn Injection
On the first turn of each session, Grok automatically searches memory for content relevant to the current project and injects it as context. This means Grok starts with knowledge from previous sessions without a reminder.
On the first turn of each session, Kigi automatically searches memory for content relevant to the current project and injects it as context. This means Kigi starts with knowledge from previous sessions without a reminder.
First-turn injection can be configured:
@@ -269,7 +269,7 @@ Memory is also searched after auto-compaction to recover relevant context that m
## Memory Search
Grok searches memory automatically, but you can also trigger searches manually in the chat:
Kigi searches memory automatically, but you can also trigger searches manually in the chat:
```
Search memory for "auth middleware patterns"
@@ -324,23 +324,23 @@ lambda = 0.7 # 0.0 = max diversity, 1.0 = pure relevance
## CLI Commands
The `grok memory` command manages memory from the shell. It has one subcommand, `clear`:
The `kigi memory` command manages memory from the shell. It has one subcommand, `clear`:
```bash
# Clear workspace memory (MEMORY.md, sessions/, and index.sqlite). This is the default scope.
grok memory clear
kigi memory clear
# The same scope, stated explicitly
grok memory clear --workspace
kigi memory clear --workspace
# Clear the global MEMORY.md
grok memory clear --global
kigi memory clear --global
# Clear both workspace and global memory
grok memory clear --all
kigi memory clear --all
# Skip the confirmation prompt (-y is the short form)
grok memory clear --yes
kigi memory clear --yes
```
To edit memory from the shell, open the files in your editor directly -- for example, `$EDITOR ~/.kigi/memory/MEMORY.md`.
@@ -386,7 +386,7 @@ To edit memory from the shell, open the files in your editor directly -- for exa
| Key | Default | Description |
|-----|---------|-------------|
| `enabled` | `true` | Enable first-turn memory injection |
| `min_score` | unset | Score threshold for first-turn results. When unset, Grok applies no threshold, which is equivalent to `0.0`. |
| `min_score` | unset | Score threshold for first-turn results. When unset, Kigi applies no threshold, which is equivalent to `0.0`. |
### Dream Settings (`[memory.dream]`)
@@ -407,7 +407,7 @@ You configure flush under `[compaction]`, not `[memory]`, because it is a compac
| `enabled` | `true` | Enable the pre-compaction memory flush |
| `soft_threshold_tokens` | `4000` | Token headroom before the compact threshold that triggers a flush |
| `max_flush_write_chars` | `8000` | Maximum characters the flush may write to memory |
| `flush_model` | unset | Model for the flush turn. When unset, Grok uses the session's primary model. |
| `flush_model` | unset | Model for the flush turn. When unset, Kigi uses the session's primary model. |
| `idle_timeout_secs` | unset | Idle seconds before a background flush. When unset, flush runs only before compaction. |
| `semantic_dedup_threshold` | unset | Cosine-similarity threshold for de-duplicating flushed content. When unset, defaults to `0.92`. |
@@ -428,13 +428,13 @@ You configure pruning under `[compaction]`, not `[memory]`, because it is a comp
## Memory Staleness
When a session memory is old, Grok attaches a staleness note to it in search results. Older results get a stronger reminder to verify the current state before you rely on them. These notes help you spot stored facts that might no longer be accurate. Global and workspace memories never receive staleness notes, because they hold curated long-term knowledge.
When a session memory is old, Kigi attaches a staleness note to it in search results. Older results get a stronger reminder to verify the current state before you rely on them. These notes help you spot stored facts that might no longer be accurate. Global and workspace memories never receive staleness notes, because they hold curated long-term knowledge.
---
## File Watcher
By default, Grok watches `~/.kigi/memory/` for external file changes. If you edit memory files directly (e.g., in your editor), the changes are picked up automatically on the next memory search:
By default, Kigi watches `~/.kigi/memory/` for external file changes. If you edit memory files directly (e.g., in your editor), the changes are picked up automatically on the next memory search:
- Created or modified files are reindexed.
- Deleted files have their stale chunks removed from the index.
@@ -450,8 +450,8 @@ enabled = true # default
### Memory Not Working
1. Verify memory is enabled: check `grok inspect` output.
2. Check the flag: `grok --experimental-memory` or `KIGI_MEMORY=1`.
1. Verify memory is enabled: check `kigi inspect` output.
2. Check the flag: `kigi --experimental-memory` or `KIGI_MEMORY=1`.
3. Check for `--no-memory` or `KIGI_MEMORY=0` overriding your config.
### Memory Not Appearing in Sessions
@@ -471,6 +471,6 @@ $EDITOR ~/.kigi/memory/MEMORY.md
### Debug Logging
```bash
RUST_LOG=debug KIGI_LOG_FILE=/tmp/grok.log grok
grep "memory" /tmp/grok.log
RUST_LOG=debug KIGI_LOG_FILE=/tmp/kigi.log kigi
grep "memory" /tmp/kigi.log
```
@@ -1,6 +1,6 @@
# Headless Mode and Scripting
Headless mode runs Grok non-interactively from the command line. It accepts a single prompt, executes it with full tool access, and returns the result. Use it to automate tasks, script workflows, build integrations, and parse output programmatically.
Headless mode runs Kigi non-interactively from the command line. It accepts a single prompt, executes it with full tool access, and returns the result. Use it to automate tasks, script workflows, build integrations, and parse output programmatically.
---
@@ -9,10 +9,10 @@ Headless mode runs Grok non-interactively from the command line. It accepts a si
Passing a prompt non-interactively triggers headless mode. The most common way is the `-p` flag (short for `--single`); `--prompt-json` and `--prompt-file` also trigger it:
```bash
grok -p "Your prompt here"
kigi -p "Your prompt here"
```
Grok processes the prompt, runs any necessary tools, and prints the result to stdout. The process exits when the response is complete.
Kigi processes the prompt, runs any necessary tools, and prints the result to stdout. The process exits when the response is complete.
---
@@ -21,7 +21,7 @@ Grok processes the prompt, runs any necessary tools, and prints the result to st
| Flag | Description |
| ----------------------- | ----------------------------------------------------- |
| `-p, --single <PROMPT>` | The prompt to send (or use `--prompt-json` / `--prompt-file`) |
| `-m, --model <MODEL>` | Model to use (e.g., `grok-build`) |
| `-m, --model <MODEL>` | Model to use (e.g., `kigi`) |
| `-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) |
@@ -53,13 +53,13 @@ Tool names are internal tool IDs (e.g. the shell tool is `run_terminal_cmd`, not
```bash
# Only allow read-only tools
grok -p "Explain this codebase" --tools "read_file,grep,list_dir"
kigi -p "Explain this codebase" --tools "read_file,grep,list_dir"
# Remove web access and file editing
grok -p "Review this code" --disallowed-tools "web_search,web_fetch,search_replace"
kigi -p "Review this code" --disallowed-tools "web_search,web_fetch,search_replace"
# Remove shell access
grok -p "Review this code" --disallowed-tools "run_terminal_cmd"
kigi -p "Review this code" --disallowed-tools "run_terminal_cmd"
```
`--disallowed-tools` also supports special `Agent` entries to control subagent spawning:
@@ -72,10 +72,10 @@ grok -p "Review this code" --disallowed-tools "run_terminal_cmd"
```bash
# Prevent the agent from spawning any subagents
grok -p "Fix this bug" --disallowed-tools "Agent"
kigi -p "Fix this bug" --disallowed-tools "Agent"
# Block only the explore subagent
grok -p "Refactor this module" --disallowed-tools "Agent(explore)"
kigi -p "Refactor this module" --disallowed-tools "Agent(explore)"
```
`--tools` preserves the selected agent profile's injection policy: stock profiles inject enabled optional tools before applying the allowlist, while curated profiles remain strict. The final toolset retains requested tools plus always-on MCP meta-tools. When both flags are present, `--disallowed-tools` wins.
@@ -100,13 +100,13 @@ For path rules (`Read`, `Edit`, `Write`, `Grep`), `*` is a single-level wildcard
```bash
# Deny shell commands matching "rm*"
grok -p "Clean up this project" --deny "Bash(rm*)"
kigi -p "Clean up this project" --deny "Bash(rm*)"
# Allow npm commands, deny sudo
grok -p "Set up the project" --allow "Bash(npm*)" --deny "Bash(sudo*)"
kigi -p "Set up the project" --allow "Bash(npm*)" --deny "Bash(sudo*)"
# Allow all bash commands (auto-approve without prompting)
grok -p "Build the project" --allow "Bash"
kigi -p "Build the project" --allow "Bash"
```
`--allow` and `--deny` can be repeated. Deny rules take precedence over allow rules.
@@ -147,7 +147,7 @@ When the prompt reached the model, the same object also carries spend fields
"total_tokens": 50103
},
"modelUsage": {
"grok-build": {
"kigi": {
"inputTokens": 7210,
"outputTokens": 1893,
"cacheReadInputTokens": 41000,
@@ -199,7 +199,7 @@ Usage notes:
The `sessionId` field is useful for resuming the conversation later.
On failure, Grok emits an error object (process exit non-zero). Prompt-level
On failure, Kigi emits an error object (process exit non-zero). Prompt-level
failures may also include frozen spend fields when usage was recorded:
```json
@@ -229,13 +229,13 @@ Event types:
`end` is always the last event. Spend fields on `end` match the json object
shape (snake_case uncached `input_tokens`, safe cost floats).
Grok may also emit `max_turns_reached` and `auto_compact_*` events; treat the list as non-exhaustive and switch on `type`.
Kigi may also emit `max_turns_reached` and `auto_compact_*` events; treat the list as non-exhaustive and switch on `type`.
---
## Session Management in Headless Mode
By default, each `grok -p` invocation creates a fresh session. To maintain context across calls, use session flags.
By default, each `kigi -p` invocation creates a fresh session. To maintain context across calls, use session flags.
### Named Sessions (`-s`)
@@ -243,13 +243,13 @@ To carry context across headless calls, use `-r/--resume` or `-c/--continue`. Us
```bash
# Start a headless session and capture its ID
grok -p "Review the changes in this PR" --output-format json | jq -r '.sessionId'
kigi -p "Review the changes in this PR" --output-format json | jq -r '.sessionId'
# Continue in the same session
grok -p "Now check for security issues" --resume "<id>"
kigi -p "Now check for security issues" --resume "<id>"
# Optional: create with a client-chosen UUID (must not already exist)
grok -p "hello" --session-id "$(uuidgen | tr '[:upper:]' '[:lower:]')" --output-format json
kigi -p "hello" --session-id "$(uuidgen | tr '[:upper:]' '[:lower:]')" --output-format json
```
> **Note:** `-s/--session-id` creates a new session only (valid UUID; errors if already in use). Use `-r` to resume.
@@ -260,11 +260,11 @@ The `-r/--resume` flag resumes a specific session by ID. It errors if the sessio
```bash
# Get the session ID from a previous JSON response
grok -p "Remember: the secret number is 42" --output-format json
kigi -p "Remember: the secret number is 42" --output-format json
# Output includes "sessionId": "abc123"
# Resume that exact session
grok -p "What's the secret number?" --resume abc123
kigi -p "What's the secret number?" --resume abc123
```
### Continue (`-c`)
@@ -272,7 +272,7 @@ grok -p "What's the secret number?" --resume abc123
The `-c/--continue` flag continues the most recent session in the current working directory:
```bash
grok -p "Continue where we left off" -c
kigi -p "Continue where we left off" -c
```
### Extracting Session IDs
@@ -280,7 +280,7 @@ grok -p "Continue where we left off" -c
Use `--output-format json` and parse the `sessionId` field:
```bash
grok -p "Hello" --output-format json | jq -r '.sessionId'
kigi -p "Hello" --output-format json | jq -r '.sessionId'
```
---
@@ -293,10 +293,10 @@ Headless mode works naturally with Unix pipes and redirection.
```bash
# Pipe output to a file
grok -p "Generate a README" > README.md
kigi -p "Generate a README" > README.md
# Parse JSON output with jq
grok -p "List files" --output-format json | jq -r '.text'
kigi -p "List files" --output-format json | jq -r '.text'
```
### Standard Input
@@ -305,12 +305,12 @@ Headless mode does not read piped stdin into the prompt. Pass external content t
```bash
# Include git diff as context via command substitution
grok -p "Write a concise commit message for these changes:
kigi -p "Write a concise commit message for these changes:
$(git diff --staged)"
# Or read the prompt from a file
grok --prompt-file ./prompt.txt
kigi --prompt-file ./prompt.txt
```
---
@@ -320,14 +320,14 @@ grok --prompt-file ./prompt.txt
### Automated Code Review
```bash
grok -p "Review changes for bugs and security issues." \
kigi -p "Review changes for bugs and security issues." \
--output-format json --yolo | jq -r '.text' > review.md
```
### Pre-Commit Hook
```bash
grok -p "Review staged changes for obvious bugs. Reply OK if fine, or list issues." \
kigi -p "Review staged changes for obvious bugs. Reply OK if fine, or list issues." \
--yolo --output-format json | jq -r '.text' | grep -q "^OK" || exit 1
```
@@ -335,7 +335,7 @@ grok -p "Review staged changes for obvious bugs. Reply OK if fine, or list issue
```bash
for file in src/*.js; do
grok -p "Migrate $file from CommonJS to ES modules." --yolo
kigi -p "Migrate $file from CommonJS to ES modules." --yolo
done
```
@@ -345,14 +345,14 @@ done
### Python Wrapper
Grok's headless mode can be wrapped as an OpenAI-compatible chat completion API:
Kigi's headless mode can be wrapped as an OpenAI-compatible chat completion API:
```python
import asyncio
import json
import os
class GrokChat:
class KigiChat:
"""Simple OpenAI-compatible wrapper using headless mode."""
def __init__(self, cwd="."):
@@ -360,11 +360,11 @@ class GrokChat:
self.env = {**os.environ}
def _build_cmd(self, prompt, model, stream):
return ["grok", "-p", prompt, "-m", model, "--cwd", self.cwd,
return ["kigi", "-p", prompt, "-m", model, "--cwd", self.cwd,
"--output-format", "streaming-json" if stream else "json",
"--yolo"]
async def create(self, messages, model="grok-build", stream=False):
async def create(self, messages, model="kigi", stream=False):
prompt = messages[-1]["content"] if len(messages) == 1 else "\n".join(
f"{m['role']}: {m['content']}" for m in messages
)
@@ -400,7 +400,7 @@ class GrokChat:
async def main():
client = GrokChat(cwd=".")
client = KigiChat(cwd=".")
response = await client.create(
[{"role": "user", "content": "What files are here?"}]
)
@@ -415,7 +415,7 @@ asyncio.run(main())
#!/bin/bash
# Run a code review and exit with failure if issues are found
RESULT=$(grok -p "Review this PR for bugs. Output JSON with 'issues' array." \
RESULT=$(kigi -p "Review this PR for bugs. Output JSON with 'issues' array." \
--output-format json --yolo | jq -r '.text')
ISSUE_COUNT=$(echo "$RESULT" | jq '.issues | length' 2>/dev/null || echo "0")
@@ -437,10 +437,10 @@ The `--yolo` flag enables always-approve mode (the same mode as `--permission-mo
```bash
# Format all files without asking
grok -p "Format all files" --yolo
kigi -p "Format all files" --yolo
# Run tests and fix failures
grok -p "Run the tests and fix any failures" --cwd ~/projects/my-app --yolo
kigi -p "Run the tests and fix any failures" --cwd ~/projects/my-app --yolo
```
**Use `--yolo` with care.** It grants the agent full autonomy to modify files and run commands. Only use it in trusted environments or with well-scoped prompts.
@@ -462,7 +462,7 @@ For CI environments without browser access, set `XAI_API_KEY` with an API key fr
```bash
export XAI_API_KEY="xai-..."
grok -p "Run the test suite" --yolo
kigi -p "Run the test suite" --yolo
```
---
@@ -483,9 +483,9 @@ grok -p "Run the test suite" --yolo
For headless use, authenticate with one of:
- **`XAI_API_KEY`** — simplest for CI. See [Environment Variables](#environment-variables-for-headless) above.
- **`grok login --device-auth`** (or `--device-code`) — no browser needed on the target machine.
- **`kigi login --device-auth`** (or `--device-code`) — no browser needed on the target machine.
See [Authentication > Device Code Flow](02-authentication.md#device-code-flow).
- **`grok login`** — browser-based OAuth2 on machines with a GUI.
- **`kigi login`** — browser-based OAuth2 on machines with a GUI.
If you've previously logged in, cached credentials are used automatically.
@@ -495,18 +495,18 @@ If you've previously logged in, cached credentials are used automatically.
- Headless mode starts a **fresh session by default**. Use `-r/--resume` or `-c/--continue` to maintain context across calls.
- The `--output-format json` response always includes a `sessionId` you can use with `--resume` for follow-up calls.
- Combine `--yolo` with `--rules` to set guardrails: `grok -p "..." --yolo --rules "Never delete files"`.
- For debugging, raise the log level and capture stderr: `RUST_LOG=debug grok -p "..." 2> debug.log`.
- Combine `--yolo` with `--rules` to set guardrails: `kigi -p "..." --yolo --rules "Never delete files"`.
- For debugging, raise the log level and capture stderr: `RUST_LOG=debug kigi -p "..." 2> debug.log`.
---
## Project Root Discovery
When Grok starts, it discovers the project root by walking upward from `--cwd`
When Kigi starts, it discovers the project root by walking upward from `--cwd`
(or the current directory) until it finds a `.git` directory.
Note: If `--cwd` is nested inside a large repository (such as a monorepo),
Grok discovers that repository as the project root and scopes its discovery (AGENTS.md, skills, git history) to it, which can make
Kigi discovers that repository as the project root and scopes its discovery (AGENTS.md, skills, git history) to it, which can make
startup slow. Point `--cwd` at the specific subproject you want to work in to keep
the scope small.
@@ -514,7 +514,7 @@ the scope small.
## File Locations
Grok stores data in `~/.kigi` (override with `KIGI_SHARE_DIR`; see [Environment Variables for Headless](#environment-variables-for-headless)):
Kigi stores data in `~/.kigi` (override with `KIGI_SHARE_DIR`; see [Environment Variables for Headless](#environment-variables-for-headless)):
| Path | Contents |
| ------------------------ | ------------------------------------- |
@@ -542,7 +542,7 @@ For containers or CI, mount `~/.kigi` read-only:
```bash
export XAI_API_KEY="xai-..."
export KIGI_DISABLE_AUTOUPDATER=1
grok -p "..." --no-auto-update
kigi -p "..." --no-auto-update
```
---
@@ -588,6 +588,6 @@ On SIGINT/SIGTERM:
- Session state saved up to the last completed tool call
- File modifications by tools are **not rolled back**
- Exit code is **130** for SIGINT (`128 + 2`) and **143** for SIGTERM (`128 + 15`); CI pipelines can distinguish these from a normal error (exit code `1`)
- Resume: `grok -p "continue" --resume "<id>"` or `grok -p "continue" --continue`
- Resume: `kigi -p "continue" --resume "<id>"` or `kigi -p "continue" --continue`
See [Session Management in Headless Mode](#session-management-in-headless-mode) for details on named sessions and the `-s`/`-r`/`-c` flags.
@@ -1,6 +1,6 @@
# Agent Mode (ACP) and IDE Integration
Agent mode runs Grok as an ACP (Agent Client Protocol) server for integration with IDEs, editors, and custom tooling. Unlike single-prompt mode (`grok -p`, which prints one response and exits), agent mode keeps a persistent process running and communicates through structured JSON-RPC messages.
Agent mode runs Kigi as an ACP (Agent Client Protocol) server for integration with IDEs, editors, and custom tooling. Unlike single-prompt mode (`kigi -p`, which prints one response and exits), agent mode keeps a persistent process running and communicates through structured JSON-RPC messages.
---
@@ -21,7 +21,7 @@ The [Agent Client Protocol (ACP)](https://agentclientprotocol.com) is a standard
stdio is the primary integration mode. The agent exchanges JSON-RPC messages over stdin and stdout:
```bash
grok agent stdio
kigi agent stdio
```
Clients that use this mode include:
@@ -32,11 +32,11 @@ Clients that use this mode include:
### Options
These options belong to the `grok agent` command and apply to every mode. Pass them before the mode name, for example `grok agent --model grok-build stdio`. The `stdio` subcommand itself takes no options.
These options belong to the `kigi agent` command and apply to every mode. Pass them before the mode name, for example `kigi agent --model kigi stdio`. The `stdio` subcommand itself takes no options.
| Flag | Description |
| -------------------------- | ---------------------------------------------------------------- |
| `-m, --model <MODEL>` | Set the model ID (for example, `grok-build`). |
| `-m, --model <MODEL>` | Set the model ID (for example, `kigi`). |
| `--always-approve` | Auto-approve every tool execution. (Alias: `--yolo`.) |
| `--reauth` | Run authentication before starting the agent. |
| `--agent-profile <PATH>` | Load an agent profile from a file. |
@@ -48,7 +48,7 @@ These options belong to the `grok agent` command and apply to every mode. Pass t
Run the agent as a WebSocket server for remote clients:
```bash
grok agent serve --bind 127.0.0.1:2419 --secret <token>
kigi agent serve --bind 127.0.0.1:2419 --secret <token>
```
Clients connect over WebSocket and authenticate with the secret token. If you omit `--secret`, the agent generates a token and prints it at startup; you can also supply one through the `KIGI_AGENT_SECRET` environment variable. The agent persists across reconnections, so a client can disconnect and later resume in-flight work.
@@ -60,7 +60,7 @@ Clients connect over WebSocket and authenticate with the secret token. If you om
To reach the agent over the internet instead of the local network, run a WebSocket relay server and have the agent connect to it:
```bash
grok agent headless --grok-ws-url wss://your-relay.example.com/ws
kigi agent headless --kigi-ws-url wss://your-relay.example.com/ws
```
The agent connects out to your relay, and your web clients connect to the same relay. This is useful for building web UIs where browsers cannot spawn local processes.
@@ -86,7 +86,7 @@ Communication follows the JSON-RPC 2.0 format. A typical session lifecycle:
+-------------------+----------------------+
| JSON-RPC over stdio
+-------------------v----------------------+
| grok agent stdio |
| kigi agent stdio |
| |
| +---------+ +---------+ +---------+ |
| | Session | | Tools | | MCP | |
@@ -115,7 +115,7 @@ Each update names its type, so a client can render distinct panels for reasoning
## Extension methods
Beyond the base ACP protocol, Grok defines extension methods under the `x.ai/` prefix for SpaceXAI-specific functionality. These cover:
Beyond the base ACP protocol, Kigi defines extension methods under the `x.ai/` prefix for SpaceXAI-specific functionality. These cover:
| Category | Prefix | Examples |
| -------------------------- | -------------------- | ------------------------------------------------ |
@@ -191,7 +191,7 @@ Official SDK libraries are available for multiple languages:
import { spawn, ChildProcess } from "child_process";
import * as readline from "readline";
class GrokACPChat {
class KigiACPChat {
private proc!: ChildProcess;
private sessionId!: string;
private rl!: readline.Interface;
@@ -199,7 +199,7 @@ class GrokACPChat {
constructor(private cwd = ".") {}
async init() {
this.proc = spawn("grok", ["agent", "stdio"]);
this.proc = spawn("kigi", ["agent", "stdio"]);
this.rl = readline.createInterface({ input: this.proc.stdout! });
// Initialize
@@ -257,7 +257,7 @@ class GrokACPChat {
}
// Usage
const client = await new GrokACPChat(".").init();
const client = await new KigiACPChat(".").init();
for await (const update of client.streamPrompt("List the files in this project")) {
switch (update.sessionUpdate) {
@@ -17,7 +17,7 @@ Agents and personas both customize behavior, but they operate at different level
| **How you set them** | At startup, or with agent definitions (`.md` files in `.kigi/agents/` or `~/.kigi/agents/`) | In `config.toml` (`[subagents.personas]`) or `.toml` files under `.kigi/personas/`; applied during subagent resolution |
| **What they control** | Model, tool availability, prompt body, skills | Tone, output format, task focus, and input/output contracts |
| **Who edits them** | You -- create, delete, or toggle them in the agents modal or by editing files | You -- define custom personas in config or files; bundled personas are read-only |
| **Examples** | `grok-build`, `explore`, `plan` | `researcher`, `concise` |
| **Examples** | `kigi`, `explore`, `plan` | `researcher`, `concise` |
An agent defines the session itself. A persona shapes how a subagent behaves within a session. A subagent always runs as an agent type (for example, `general-purpose`), and resolution can layer a persona on top.
@@ -79,7 +79,7 @@ instructions = "You are a thorough researcher. Always cite specific file paths."
description = "Deep investigator."
```
Grok Build discovers file-based personas from these locations, in priority order:
Kigi discovers file-based personas from these locations, in priority order:
- `.kigi/personas/*.toml` (project)
- `~/.kigi/personas/*.toml` (user)
@@ -89,7 +89,7 @@ Each file defines one persona, and the file name (without the extension) becomes
Manage personas in the Personas tab of the agents modal (`/personas`). Bundled personas are read-only; personas you define are editable.
> **Note:** Grok Build applies personas through subagent resolution and roles, not through a `spawn_subagent` parameter. The main agent does not pass a persona name when it spawns a child.
> **Note:** Kigi applies personas through subagent resolution and roles, not through a `spawn_subagent` parameter. The main agent does not pass a persona name when it spawns a child.
### Persona Fields
@@ -125,7 +125,7 @@ Each field has a `name`, an `io_type` (defaults to `file`), a `required` flag, a
### Persona Resolution
When a persona applies, Grok Build resolves the effective model and reasoning effort in this order, highest priority first:
When a persona applies, Kigi resolves the effective model and reasoning effort in this order, highest priority first:
1. Explicit spawn-time override
2. Role default
@@ -193,7 +193,7 @@ For tasks that modify files, run a subagent in an isolated git worktree with `is
- Its changes stay isolated from the parent until you merge them.
- The subagent's result includes the worktree path.
Grok Build manages worktrees through the `x.ai/git/worktree/*` extension methods, including an apply operation that merges changes back into the main working directory.
Kigi manages worktrees through the `x.ai/git/worktree/*` extension methods, including an apply operation that merges changes back into the main working directory.
---
@@ -209,7 +209,7 @@ explore = true # default -- omit to keep enabled
plan = false # disable the plan subagent
[subagents.models]
explore = "grok-build" # route explore to a specific model
explore = "kigi" # route explore to a specific model
```
Per-type model overrides apply for any parent. Without an override, a subagent inherits the parent's model.
@@ -222,7 +222,7 @@ Define custom roles with their own capability and model defaults:
[subagents.roles.researcher]
description = "Deep research agent"
default_capability_mode = "read-only"
model = "grok-build"
model = "kigi"
prompt_file = ".kigi/prompts/researcher.md"
```
@@ -234,13 +234,13 @@ instructions = "Be concise. No filler words."
# instructions_file = ".kigi/personas/concise.md" # or load from a file
```
Grok Build also discovers roles from `.kigi/roles/*.toml` and personas from `.kigi/personas/*.toml`. Inline `config.toml` definitions take precedence over files.
Kigi also discovers roles from `.kigi/roles/*.toml` and personas from `.kigi/personas/*.toml`. Inline `config.toml` definitions take precedence over files.
---
## The Tasks Pane (TUI)
Grok Build shows running and finished work in side panes on the agent screen:
Kigi shows running and finished work in side panes on the agent screen:
- Press `Ctrl+B` to toggle the tasks pane, which lists active and completed subagents and background commands with their status.
- Press `Ctrl+T` to toggle the separate todo pane.
@@ -259,7 +259,7 @@ Subagents appear in several places in the interactive TUI:
When a subagent is spawned, a compact lifecycle block is added to the *parent's* scrollback:
- `Subagent running: "do the thing" (Implementer · grok-3) — Thinking`
- `Subagent running: "do the thing" (Implementer · kigi-3) — Thinking`
- Or for background subagents: `Subagent started: "..."`
While running, the block shows a live activity suffix (e.g. "Running: cargo test", "Compacting", "Retrying (2/3)") pulled from the child's turn tracker. The bullet animates (or is colored) according to state.
@@ -1,6 +1,6 @@
# Session Management
Grok saves every conversation to disk automatically. Whether you work in the TUI, in headless mode, or over agent stdio, Grok records the exchange as a session. You can resume, rewind, or compact it. This document describes how to manage sessions.
Kigi saves every conversation to disk automatically. Whether you work in the TUI, in headless mode, or over agent stdio, Kigi records the exchange as a session. You can resume, rewind, or compact it. This document describes how to manage sessions.
---
@@ -15,13 +15,13 @@ A session is a persistent conversation with full history. It includes:
- Token usage and turn counts
- Subagent sessions (when enabled)
Sessions are identified by a unique session ID (a UUIDv7 when Grok generates it; a client may supply its own ID with `-s`) and stored on disk under `~/.kigi/sessions/`. Set `KIGI_SHARE_DIR` to override the base directory; when it is unset, Grok uses `~/.kigi`.
Sessions are identified by a unique session ID (a UUIDv7 when Kigi generates it; a client may supply its own ID with `-s`) and stored on disk under `~/.kigi/sessions/`. Set `KIGI_SHARE_DIR` to override the base directory; when it is unset, Kigi uses `~/.kigi`.
---
## Storage Layout
Grok stores each session in its own directory, grouped by working directory. It URL-encodes the working directory to name the group. When the encoded name exceeds 255 bytes, it instead uses a slug plus a hash and records the original path in a `.cwd` file inside the group.
Kigi stores each session in its own directory, grouped by working directory. It URL-encodes the working directory to name the group. When the encoded name exceeds 255 bytes, it instead uses a slug plus a hash and records the original path in a `.cwd` file inside the group.
```
~/.kigi/sessions/<encoded-cwd>/<session-id>/
@@ -54,13 +54,13 @@ This clears the current context and begins a new conversation. Alias: `/clear`.
### Exit
End the session and quit Grok:
End the session and quit Kigi:
```
/quit
```
Alias: `/exit`. To leave the current session but stay in Grok, use `/home` to return to the welcome screen.
Alias: `/exit`. To leave the current session but stay in Kigi, use `/home` to return to the welcome screen.
---
@@ -85,14 +85,14 @@ To switch between, rename, or close the sessions that are currently active (the
Resume a specific session by ID:
```bash
grok --resume <session-id>
kigi --resume <session-id>
```
Run `grok --resume` without an ID to resume the most recent session for the current directory.
Run `kigi --resume` without an ID to resume the most recent session for the current directory.
### From the Welcome Screen
When you launch `grok`, the welcome screen lists recent sessions for the current directory. Select one to resume it.
When you launch `kigi`, the welcome screen lists recent sessions for the current directory. Select one to resume it.
---
@@ -128,7 +128,7 @@ Alias: `/title`.
/rewind
```
When you run `/rewind` (or press **Esc Esc** within 800ms while idle with an empty prompt and conversation messages), Grok:
When you run `/rewind` (or press **Esc Esc** within 800ms while idle with an empty prompt and conversation messages), Kigi:
1. Shows a list of rewind points (one per user prompt)
2. Lets you select which point to rewind to
@@ -154,7 +154,7 @@ The optional `context` argument lets you provide additional instructions about w
### Auto-Compact
Grok automatically compacts the conversation when the context window approaches its limit. You will see a notification when auto-compact triggers. The `context_window` setting on your model configuration controls when this threshold is reached.
Kigi automatically compacts the conversation when the context window approaches its limit. You will see a notification when auto-compact triggers. The `context_window` setting on your model configuration controls when this threshold is reached.
---
@@ -184,13 +184,13 @@ In headless mode, you manage sessions through command-line flags:
```bash
# New session each time (default)
grok -p "Hello"
kigi -p "Hello"
# Resume an existing session by ID (errors if it does not exist)
grok -p "Continue where we left off" -r <session-id>
kigi -p "Continue where we left off" -r <session-id>
# Continue the most recent session in the current directory
grok -p "What were we doing?" -c
kigi -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`.
@@ -200,7 +200,7 @@ Use `-s`/`--session-id` only to **create** a new session with a **UUID** (errors
To read the session ID back, request JSON output:
```bash
grok -p "Hello" --output-format json | jq -r '.sessionId'
kigi -p "Hello" --output-format json | jq -r '.sessionId'
```
---
@@ -228,28 +228,28 @@ The agent persists all session updates automatically. Clients can reconnect and
---
## The grok sessions Subcommand
## The kigi sessions Subcommand
List or search sessions from the command line. `grok sessions` requires a subcommand:
List or search sessions from the command line. `kigi sessions` requires a subcommand:
```bash
# List recent sessions for the current directory
grok sessions list
kigi sessions list
# Limit the number of results (default 20)
grok sessions list --limit 50
kigi sessions list --limit 50
# Search sessions by keyword (matches titles and prompts)
grok sessions search "rate limit"
kigi sessions search "rate limit"
```
`grok sessions list` shows sessions for the current working directory, grouped by worktree label. Each row lists the session ID, the creation and update dates, the source status, and the summary. `grok sessions search` combines a local SQLite index with remote results.
`kigi sessions list` shows sessions for the current working directory, grouped by worktree label. Each row lists the session ID, the creation and update dates, the source status, and the summary. `kigi sessions search` combines a local SQLite index with remote results.
---
## Worktree Sessions
When working with subagents or session forks, Grok can create isolated git worktrees per session. Each worktree gets its own copy of the working directory, so file changes in one session do not affect another.
When working with subagents or session forks, Kigi can create isolated git worktrees per session. Each worktree gets its own copy of the working directory, so file changes in one session do not affect another.
Worktree sessions are managed internally through the `x.ai/git/worktree/*` extension methods. Key operations:
@@ -257,7 +257,7 @@ Worktree sessions are managed internally through the `x.ai/git/worktree/*` exten
- **Apply**: Merge worktree changes back into the main working directory
- **Remove**: Clean up a worktree when the session is done
Resume a session in a fresh worktree with `grok -w -r <session-id>`.
Resume a session in a fresh worktree with `kigi -w -r <session-id>`.
---
@@ -265,13 +265,13 @@ Resume a session in a fresh worktree with `grok -w -r <session-id>`.
### Persistence Format
Grok stores the conversation as newline-delimited JSON (JSONL). Each line in `updates.jsonl` is a self-contained ACP session update event. This format supports:
Kigi stores the conversation as newline-delimited JSON (JSONL). Each line in `updates.jsonl` is a self-contained ACP session update event. This format supports:
- Incremental writes (append-only during a session)
- Efficient streaming reads (for session restore)
- Easy debugging (each line is valid JSON)
The smaller state files -- `summary.json`, `plan.json`, and `signals.json` -- are plain JSON rather than JSONL. JSONL is the source of truth for session content; `grok sessions search` additionally maintains a local SQLite FTS5 index over session titles and prompts for fast keyword search.
The smaller state files -- `summary.json`, `plan.json`, and `signals.json` -- are plain JSON rather than JSONL. JSONL is the source of truth for session content; `kigi sessions search` additionally maintains a local SQLite FTS5 index over session titles and prompts for fast keyword search.
### Session Metadata
@@ -10,13 +10,13 @@ Sandbox mode is off by default.
```bash
# Run with workspace sandbox (read everywhere, write to CWD + temp dirs + ~/.kigi/)
grok --sandbox workspace
kigi --sandbox workspace
# Read-only mode (read everywhere, write only to ~/.kigi/ + temp dirs)
grok --sandbox read-only
kigi --sandbox read-only
# Most restrictive profile (read CWD + system paths, write CWD + temp dirs + ~/.kigi/, no child network)
grok --sandbox strict
kigi --sandbox strict
```
---
@@ -70,12 +70,12 @@ deny = ["/data/shared-secrets", "**/.env", "**/*.pem"]
Use the custom profile:
```bash
grok --sandbox project
kigi --sandbox project
```
A custom profile can't reuse a built-in name. `--sandbox devbox` always runs the built-in `devbox` profile, shadowing any `[profiles.devbox]` you define.
When the global and per-project files define the same custom profile name, the user-level definition takes precedence and the project definition is ignored. If those two definitions differ, Grok warns about the conflict at startup — on the welcome screen in the TUI, and on stderr for headless runs. Identical duplicate definitions do not produce a warning.
When the global and per-project files define the same custom profile name, the user-level definition takes precedence and the project definition is ignored. If those two definitions differ, Kigi warns about the conflict at startup — on the welcome screen in the TUI, and on stderr for headless runs. Identical duplicate definitions do not produce a warning.
### Custom Profile Fields
@@ -92,7 +92,7 @@ When the global and per-project files define the same custom profile name, the u
> bind-over on Linux, so a denied path can neither be read (via `bash`, `grep`, or
> subagents) nor relocated out of the deny set and read elsewhere (the
> `mv secret x && cat x` bypass is closed). On **Linux**, read-deny requires
> `bubblewrap`: if it is missing (or any single deny path can't be bound), Grok
> `bubblewrap`: if it is missing (or any single deny path can't be bound), Kigi
> refuses to start rather than run with denied paths exposed (`devbox`, which only
> write-denies `/data`, still falls back to Landlock). Writes to paths **not** in
> `deny` are controlled by what you grant in `read_write`.
@@ -112,7 +112,7 @@ When the global and per-project files define the same custom profile name, the u
> Brace alternation (`{a,b}`), backslash-escapes, and the unusual class forms
> `[]…]` (literal `]` first) and POSIX `[[:…:]]` are **not** supported, so the two
> platforms can never interpret a glob differently. A glob using an unsupported
> metacharacter, or one that is malformed, makes Grok **refuse to start** (fail
> metacharacter, or one that is malformed, makes Kigi **refuse to start** (fail
> closed) on **both** platforms — write `*.pem` and `*.key` as separate entries
> rather than `*.{pem,key}`.
>
@@ -121,19 +121,19 @@ When the global and per-project files define the same custom profile name, the u
> matching. Enforcement otherwise differs by platform:
>
> - **macOS is airtight:** each glob becomes a Seatbelt regex applied at runtime,
> so matching files are denied **even if created after Grok starts**.
> so matching files are denied **even if created after Kigi starts**.
> - **Linux is best-effort:** a mount namespace can't glob at runtime, so each
> glob is expanded to the files that **exist at launch** and those are bound
> over. Files created **later** that match a glob are **not** covered — name
> exact paths for anything that must be airtight on Linux. A glob that matches
> too many files, or whose tree is too deep/broad to walk, makes Grok **refuse
> too many files, or whose tree is too deep/broad to walk, makes Kigi **refuse
> to start** rather than under-enforce.
---
## How It Works
The sandbox is applied to the **entire grok process** at startup using kernel primitives -- not per-command wrapping. This means all tool operations are covered:
The sandbox is applied to the **entire kigi process** at startup using kernel primitives -- not per-command wrapping. This means all tool operations are covered:
- `read_file`, `search_replace`, `list_dir` -- restricted by Landlock/Seatbelt in-process
- `bash` commands, `grep` (rg) -- child processes inherit FS restrictions automatically
@@ -146,8 +146,8 @@ The sandbox is **irreversible** once applied. The agent cannot relax restriction
## Resuming Sessions
The profile a session was started with is saved with the session and is **fixed
for the life of the session**. When you resume it (`grok --resume <id>`,
`grok --continue`, or `grok -r`), Grok restores that same profile automatically —
for the life of the session**. When you resume it (`kigi --resume <id>`,
`kigi --continue`, or `kigi -r`), Kigi restores that same profile automatically —
so a session started with `--sandbox workspace` won't silently come back under a
stricter default and break commands that previously worked.
@@ -176,7 +176,7 @@ Profile resolution order for a **new** session:
| Linux | Landlock | Kernel 5.13 or later |
| macOS | Seatbelt | macOS (all versions) |
If the sandbox cannot be applied (e.g., unsupported kernel, missing entitlements), Grok logs a warning and continues without enforcement. The exception is an explicitly-requested **custom profile**: on **both macOS and Linux**, if it cannot be applied (unknown profile, malformed `sandbox.toml`, or — on Linux — `bubblewrap` unavailable for a non-empty `deny`), Grok refuses to start rather than run with its denied paths exposed.
If the sandbox cannot be applied (e.g., unsupported kernel, missing entitlements), Kigi logs a warning and continues without enforcement. The exception is an explicitly-requested **custom profile**: on **both macOS and Linux**, if it cannot be applied (unknown profile, malformed `sandbox.toml`, or — on Linux — `bubblewrap` unavailable for a non-empty `deny`), Kigi refuses to start rather than run with its denied paths exposed.
---
@@ -1,6 +1,6 @@
# Background Tasks and Monitoring
Grok runs long-lived processes without blocking the conversation. This document covers background commands, the `/loop` command, the `monitor` tool, and the scheduler.
Kigi runs long-lived processes without blocking the conversation. This document covers background commands, the `/loop` command, the `monitor` tool, and the scheduler.
---
@@ -100,7 +100,7 @@ The `monitor` tool streams events from a long-running script. Each line of outpu
### How It Works
1. You provide a shell command (`command`) and a short `description` that appears in every notification.
2. Grok merges the command's stdout and stderr into a single output file.
2. Kigi merges the command's stdout and stderr into a single output file.
3. Each new line in that file becomes a notification delivered to the conversation.
4. The monitor runs until the command exits or you stop it.
@@ -143,7 +143,7 @@ Stop persistent monitors with `kill_command_or_subagent(task_id)`.
### Volume Control
If a monitor produces too many events, Grok stops it automatically. When this happens, restart the monitor with a tighter filter. Prefer `grep --line-buffered`, `awk`, or a wrapper script that emits only the events you care about.
If a monitor produces too many events, Kigi stops it automatically. When this happens, restart the monitor with a tighter filter. Prefer `grep --line-buffered`, `awk`, or a wrapper script that emits only the events you care about.
---
@@ -1,6 +1,6 @@
# Terminal Support and Troubleshooting
Grok Build runs as a full-screen TUI. To draw the interface, it relies on terminal escape sequences for color, clipboard, mouse, and full-screen control. Some terminals, multiplexers, and SSH sessions handle these sequences differently.
Kigi runs as a full-screen TUI. To draw the interface, it relies on terminal escape sequences for color, clipboard, mouse, and full-screen control. Some terminals, multiplexers, and SSH sessions handle these sequences differently.
## Quick Fixes
@@ -33,7 +33,7 @@ tmux source-file ~/.tmux.conf
# or detach and reattach
```
### Live diagnostics inside Grok
### Live diagnostics inside Kigi
Run this slash command:
@@ -41,13 +41,13 @@ Run this slash command:
/terminal-setup
```
The command reports the terminal, multiplexer, **color level**, **available themes**, and clipboard routes Grok detected, then lists any issues and how to fix them. When color is below truecolor, it explains how to unlock the truecolor-only themes (TokyoNight, RosePineMoon, OscuraMidnight) — or notes that Terminal.app is inherently 256-color. The aliases `/terminal-check` and `/terminal-info` run the same command.
The command reports the terminal, multiplexer, **color level**, **available themes**, and clipboard routes Kigi detected, then lists any issues and how to fix them. When color is below truecolor, it explains how to unlock the truecolor-only themes (TokyoNight, RosePineMoon, OscuraMidnight) — or notes that Terminal.app is inherently 256-color. The aliases `/terminal-check` and `/terminal-info` run the same command.
---
## Detected Terminals
Grok detects these terminal emulators from environment variables:
Kigi detects these terminal emulators from environment variables:
- **Apple Terminal** (Terminal.app)
- **Ghostty**
@@ -60,13 +60,13 @@ Grok detects these terminal emulators from environment variables:
- **foot** (Wayland-native, Linux)
- **VS Code**, **Cursor**, **Windsurf**, and **Zed** integrated terminals
- **JetBrains** IDE terminals (IntelliJ, PhpStorm, and others)
- **Grok Desktop**
- **Kigi Desktop**
- **VTE**-based terminals (GNOME Terminal, GNOME Console, Tilix)
- **Windows Terminal**
Detection has these limitations:
- Inside tmux, the variables Grok needs to identify the terminal don't reach the pager.
- Inside tmux, the variables Kigi needs to identify the terminal don't reach the pager.
- Over SSH, many terminal variables aren't forwarded.
- tmux's global environment (`tmux -g`) reflects the first client that attached to the server, not your current session.
@@ -78,34 +78,34 @@ Detection has these limitations:
**Cause**: `COLORTERM` not set or tmux not configured for 24-bit RGB.
**Fix**: Apply the two settings above, then restart Grok.
**Fix**: Apply the two settings above, then restart Kigi.
**Verify**: Run `/terminal-setup`. Expect `color truecolor` and `themes all`. If `color` is `256` or `basic`, the issues section has the unlock fix.
### Problem: Clipboard problems
Grok writes to the clipboard through up to three routes, which match the **Clipboard routes** section of `/terminal-setup`:
Kigi writes to the clipboard through up to three routes, which match the **Clipboard routes** section of `/terminal-setup`:
- **native**Grok always writes to the native OS clipboard first.
- **tmux buffer** — inside tmux, Grok also writes to the tmux paste buffer (`tmux load-buffer`).
- **OSC 52**Grok emits the OSC 52 escape sequence so the outer terminal updates its clipboard. Grok always emits OSC 52 inside tmux. Outside tmux, it emits OSC 52 on Linux, over SSH, or in a container without a display.
- **native**Kigi always writes to the native OS clipboard first.
- **tmux buffer** — inside tmux, Kigi also writes to the tmux paste buffer (`tmux load-buffer`).
- **OSC 52**Kigi emits the OSC 52 escape sequence so the outer terminal updates its clipboard. Kigi always emits OSC 52 inside tmux. Outside tmux, it emits OSC 52 on Linux, over SSH, or in a container without a display.
**Linux Wayland**: on compositors that support the data-control protocol (GNOME 48+, KDE, Sway, Hyprland — the `data-control` line in `/terminal-setup` shows `yes`) copies work even if the terminal loses focus mid-copy. On older compositors (GNOME 46/47), keep the terminal focused until the copy toast confirms, and install the `wl-clipboard` package (provides `wl-copy`) for the most reliable route — Grok shows a startup warning when this applies. If data-control misbehaves on your compositor, set `KIGI_CLIPBOARD_NO_DATA_CONTROL=1` to stop Grok from speaking that protocol entirely — copies then go through the CLI tools (`wl-copy`/`xclip`).
**Linux Wayland**: on compositors that support the data-control protocol (GNOME 48+, KDE, Sway, Hyprland — the `data-control` line in `/terminal-setup` shows `yes`) copies work even if the terminal loses focus mid-copy. On older compositors (GNOME 46/47), keep the terminal focused until the copy toast confirms, and install the `wl-clipboard` package (provides `wl-copy`) for the most reliable route — Kigi shows a startup warning when this applies. If data-control misbehaves on your compositor, set `KIGI_CLIPBOARD_NO_DATA_CONTROL=1` to stop Kigi from speaking that protocol entirely — copies then go through the CLI tools (`wl-copy`/`xclip`).
**Linux X11 selections**: X11 **PRIMARY** and **CLIPBOARD** are separate. Selecting text usually fills PRIMARY; an explicit Copy action fills CLIPBOARD. In Grok:
**Linux X11 selections**: X11 **PRIMARY** and **CLIPBOARD** are separate. Selecting text usually fills PRIMARY; an explicit Copy action fills CLIPBOARD. In Kigi:
- An unmodified middle click reads PRIMARY only when `DISPLAY` is non-empty. Pure X11 can fall back to the native arboard reader. XWayland must have `xclip` or `xsel` on `PATH`; Grok deliberately disables the arboard fallback there so it cannot substitute Wayland PRIMARY.
- An unmodified middle click reads PRIMARY only when `DISPLAY` is non-empty. Pure X11 can fall back to the native arboard reader. XWayland must have `xclip` or `xsel` on `PATH`; Kigi deliberately disables the arboard fallback there so it cannot substitute Wayland PRIMARY.
- `Ctrl+V` reads CLIPBOARD only and never falls back to PRIMARY. To fill CLIPBOARD from a shell, run `printf %s "text" | xclip -selection clipboard`.
- `Shift+Insert` remains the terminal-native selected-text paste. Native Wayland PRIMARY behavior is compositor/terminal-specific and is not inferred from `TERM` or an incoming mouse event.
**SSH and selected text**: a remote Grok process usually cannot read the local terminal's PRIMARY or CLIPBOARD selection. Use terminal-native `Shift+Insert`, or hold `Shift` while middle-clicking when your terminal uses that gesture to bypass mouse reporting. The terminal then sends the local selection through the PTY instead of asking the remote process to access it.
**SSH and selected text**: a remote Kigi process usually cannot read the local terminal's PRIMARY or CLIPBOARD selection. Use terminal-native `Shift+Insert`, or hold `Shift` while middle-clicking when your terminal uses that gesture to bypass mouse reporting. The terminal then sends the local selection through the PTY instead of asking the remote process to access it.
**Known limitation — Apple Terminal + SSH**:
Apple Terminal ignores OSC 52, so copying from a Grok session over SSH can't reach your local clipboard. Use the workaround below.
Apple Terminal ignores OSC 52, so copying from a Kigi session over SSH can't reach your local clipboard. Use the workaround below.
**Temporary workaround**: Use `grok wrap ssh` instead of plain `ssh` (for example, `grok wrap ssh user@host`). It runs the command in a local PTY that intercepts OSC 52 sequences, including tmux-wrapped ones, and writes their contents to your local clipboard. The same command wraps anything else whose clipboard can't reach you — for example `grok wrap docker exec -it <container> bash` or `grok wrap kubectl exec -it <pod> -- bash`.
**Temporary workaround**: Use `kigi wrap ssh` instead of plain `ssh` (for example, `kigi wrap ssh user@host`). It runs the command in a local PTY that intercepts OSC 52 sequences, including tmux-wrapped ones, and writes their contents to your local clipboard. The same command wraps anything else whose clipboard can't reach you — for example `kigi wrap docker exec -it <container> bash` or `kigi wrap kubectl exec -it <pod> -- bash`.
> **Warning**: `grok wrap` is **experimental** and may misbehave in some setups.
> **Warning**: `kigi wrap` is **experimental** and may misbehave in some setups.
**iTerm2 setting**:
iTerm2 requires explicit permission for OSC 52:
@@ -113,7 +113,7 @@ iTerm2 requires explicit permission for OSC 52:
1. iTerm2 → **Settings****General** → **Selection**
2. Enable **"Applications in terminal may access clipboard"**
This setting is off by default for security reasons. Without it, OSC 52 writes from Grok (or any TUI) will be ignored.
This setting is off by default for security reasons. Without it, OSC 52 writes from Kigi (or any TUI) will be ignored.
**Fix for other cases**:
- `set -g set-clipboard on` in tmux config
@@ -124,13 +124,13 @@ This setting is off by default for security reasons. Without it, OSC 52 writes f
**Cause**: Zellij, tmux control mode (`tmux -CC`), or config set to `never`.
**Fix**:
- In Zellij or control mode, Grok intentionally runs inline (no alt screen).
- In Zellij or control mode, Kigi intentionally runs inline (no alt screen).
- Set `[terminal] alt_screen = "always"` in `~/.kigi/pager.toml` to force fullscreen.
- Use the CLI flag `--no-alt-screen` to disable alt-screen mode entirely (useful for debugging or when the alternate screen causes issues in your terminal).
### Problem: Zellij keybindings interfere with Grok (Ctrl+g, Ctrl+o, etc.)
### Problem: Zellij keybindings interfere with Kigi (Ctrl+g, Ctrl+o, etc.)
Zellij intercepts many Ctrl/Alt key combinations before they reach full-screen TUIs like Grok.
Zellij intercepts many Ctrl/Alt key combinations before they reach full-screen TUIs like Kigi.
**Best fix** (Zellij 0.41+): Switch to the **"Unlock-First (non-colliding)"** preset:
@@ -139,15 +139,15 @@ Zellij intercepts many Ctrl/Alt key combinations before they reach full-screen T
3. Select **"Unlock-First (non-colliding)"**
4. Press `Enter` (or `Ctrl+a` to save permanently)
After this, Zellij starts **locked**. Most keys pass through to Grok. Press `Ctrl+g` to temporarily unlock Zellij when you need its pane/session management.
After this, Zellij starts **locked**. Most keys pass through to Kigi. Press `Ctrl+g` to temporarily unlock Zellij when you need its pane/session management.
Zellij recommends this approach for TUI users.
### Problem: `Ctrl+Enter` doesn't interject in WezTerm
**Cause**: WezTerm ships with the Kitty keyboard protocol disabled. Grok relies on it to tell `Ctrl+Enter` (interject) and `Shift+Enter` (send in multiline mode) apart from plain `Enter`. Most other terminals enable the protocol when Grok requests it.
**Cause**: WezTerm ships with the Kitty keyboard protocol disabled. Kigi relies on it to tell `Ctrl+Enter` (interject) and `Shift+Enter` (send in multiline mode) apart from plain `Enter`. Most other terminals enable the protocol when Kigi requests it.
For the same reason, in Apple Terminal, Grok binds `Ctrl+O` to interject.
For the same reason, in Apple Terminal, Kigi binds `Ctrl+O` to interject.
**Fix**:
@@ -157,9 +157,9 @@ Add this after `config = wezterm.config_builder()` in `~/.config/wezterm/wezterm
config.enable_kitty_keyboard = true
```
Reload (`Cmd+Shift+R` or restart WezTerm) and restart `grok`.
Reload (`Cmd+Shift+R` or restart WezTerm) and restart `kigi`.
**Verify**: Run `/terminal-setup` inside Grok. While a turn is active, you see the interject hint, and `Ctrl+Enter` interjects.
**Verify**: Run `/terminal-setup` inside Kigi. While a turn is active, you see the interject hint, and `Ctrl+Enter` interjects.
**Quick workaround** (no global change):
@@ -176,24 +176,24 @@ table.insert(config.keys, {
**Cause**: VS Code's integrated terminal (and the Cursor / Windsurf / Zed
forks) use xterm.js, which only partially implements the Kitty keyboard
protocol — it mis-encodes shifted printable keys (`!@#$%^&*()` arrive as
plain digits). Grok therefore never negotiates the protocol for these
plain digits). Kigi therefore never negotiates the protocol for these
terminals. Without it, xterm.js sends a bare `CR` for `Shift+Enter`,
byte-for-byte identical to plain `Enter`, so the chord can't be told apart
and the prompt submits.
This also affects VS Code reached **over SSH** (e.g. into a devbox or
container): `TERM_PROGRAM` isn't forwarded, so Grok sees an `Unknown`
container): `TERM_PROGRAM` isn't forwarded, so Kigi sees an `Unknown`
terminal and skips the protocol for the same reason.
**Fix**: Use **`Alt+Enter`** to insert a newline. xterm.js delivers it
reliably as `ESC`+`CR` regardless of the keyboard protocol, and Grok's
reliably as `ESC`+`CR` regardless of the keyboard protocol, and Kigi's
prompt hint bar advertises `Alt+Enter: newline` whenever it detects this
situation. Run `/terminal-setup` to confirm — the `newline` row shows
`Alt+Enter` when `Shift+Enter` is unavailable.
### Problem: Mouse scrolling stops working (native scrollbar takes over)
If Grok's mouse-driven scrolling stops responding and your terminal falls back to its native scrollbar, mouse reporting is off.
If Kigi's mouse-driven scrolling stops responding and your terminal falls back to its native scrollbar, mouse reporting is off.
**Apple Terminal**: Go to **View > Allow Mouse Reporting** (keyboard shortcut `Cmd+R`) to re-enable it. A checkmark appears next to the option when active.
@@ -1,6 +1,6 @@
# Permissions and Safety Controls
Grok can read files, search code, edit files, and run shell commands. The permission system controls what the agent is allowed to do. You can combine several independent layers: permission rules, permission modes, hooks, and the OS-level sandbox.
Kigi can read files, search code, edit files, and run shell commands. The permission system controls what the agent is allowed to do. You can combine several independent layers: permission rules, permission modes, hooks, and the OS-level sandbox.
This guide explains how a tool call is authorized, how to configure permission rules from the CLI, native configuration, or Claude settings, and how to use `PreToolUse` hooks for allow lists that apply in every mode.
@@ -100,13 +100,13 @@ Do not use `permission_mode` for this; it is a user-switchable default, not a lo
The user-level `~/.kigi/requirements.toml` is under the user's control, so a developer can remove the lock by editing that file. For enforcement that users cannot override, deploy the setting in the root-owned system file `/etc/kigi/requirements.toml`.
> **Note:** Grok honors the permission rules in Claude Code's `managed-settings.json`, but not its `disableBypassPermissionsMode` lock. To disable always-approve in Grok, use `requirements.toml` as shown above.
> **Note:** Kigi honors the permission rules in Claude Code's `managed-settings.json`, but not its `disableBypassPermissionsMode` lock. To disable always-approve in Kigi, use `requirements.toml` as shown above.
---
## Configuring Permissions
Grok reads permission rules from three compatible sources. Rules from all sources are merged into one set; a rule's effect depends on its action (`deny` > `ask` > `allow`), not on which file it came from.
Kigi reads permission rules from three compatible sources. Rules from all sources are merged into one set; a rule's effect depends on its action (`deny` > `ask` > `allow`), not on which file it came from.
### Where Permission Rules Live (Scopes)
@@ -117,13 +117,13 @@ Permission rules can be global (all projects), project-scoped (one repository),
| Global (all projects) | `~/.kigi/config.toml` | No |
| Project (committed) | `<project>/.kigi/config.toml` | Yes (commit it) |
| Project (personal) | `<project>/.claude/settings.local.json` | No (gitignore it) |
| Interactive grants | Stored internally by Grok, per project | No |
| Interactive grants | Stored internally by Kigi, per project | No |
Notes on scoping:
- Grok discovers a `.kigi/config.toml` at every directory level from the repository root down to your working directory, so a subdirectory can add rules on top of the repo root's.
- Kigi discovers a `.kigi/config.toml` at every directory level from the repository root down to your working directory, so a subdirectory can add rules on top of the repo root's.
- Rules from all scopes are merged into one rule set; `deny` > `ask` > `allow` applies across scopes, so a global `deny` cannot be overridden by a project `allow`.
- Grok has no native `config.local.toml`. For personal, uncommitted rules in a project, use `.claude/settings.local.json`; Grok reads it directly (see [Claude Code Compatibility](#3-claude-code-compatibility-claudesettingsjson)).
- Kigi has no native `config.local.toml`. For personal, uncommitted rules in a project, use `.claude/settings.local.json`; Kigi reads it directly (see [Claude Code Compatibility](#3-claude-code-compatibility-claudesettingsjson)).
- Interactive "Always allow" decisions are stored outside the repository, scoped to the project (see [Interactive Approvals](#interactive-approvals-and-where-they-persist)).
To stop prompts for a specific command in one project, add a narrow allow rule to that project's `.kigi/config.toml` (or `.claude/settings.json`):
@@ -138,7 +138,7 @@ This approves only the listed commands. Always-approve mode, by contrast, approv
### 1. CLI Flags
```bash
grok -p "Review the API changes" \
kigi -p "Review the API changes" \
--allow 'Bash(git *)' \
--allow 'Bash(gh *)' \
--allow 'Read' \
@@ -179,7 +179,7 @@ Because `deny` always wins, you cannot combine these `allow` rules with a catch-
Rules from the global `~/.kigi/config.toml` and every project `.kigi/config.toml` (from the repo root down to your working directory) are merged into one rule set, alongside any `.claude/settings.json` rules.
Managed configuration deployed by your organization also contributes `[permission]` rules: the system `/etc/kigi/managed_config.toml`, and a user-level copy that Grok maintains automatically at `~/.kigi/managed_config.toml`. Managed rules merge like rules from any other source, with two properties specific to managed `allow` rules: your own `deny` and `ask` rules win over a managed `allow` (severity ordering), and a catch-all managed `allow` is ignored when always-approve is locked off. For rules that users cannot edit away, use the root-owned system `/etc/kigi/requirements.toml`.
Managed configuration deployed by your organization also contributes `[permission]` rules: the system `/etc/kigi/managed_config.toml`, and a user-level copy that Kigi maintains automatically at `~/.kigi/managed_config.toml`. Managed rules merge like rules from any other source, with two properties specific to managed `allow` rules: your own `deny` and `ask` rules win over a managed `allow` (severity ordering), and a catch-all managed `allow` is ignored when always-approve is locked off. For rules that users cannot edit away, use the root-owned system `/etc/kigi/requirements.toml`.
Permission rules from every source are read once, when a session starts. Changes apply to the next session.
@@ -202,7 +202,7 @@ allow = [
### 3. Claude Code Compatibility (`.claude/settings.json`)
Grok reads `~/.claude/settings.json` and `~/.claude/settings.local.json`, plus the project-level `<project>/.claude/settings.json` and `settings.local.json` (walking up to the repo root). The native `.kigi` source for permission rules is `config.toml`, described in the section above.
Kigi reads `~/.claude/settings.json` and `~/.claude/settings.local.json`, plus the project-level `<project>/.claude/settings.json` and `settings.local.json` (walking up to the repo root). The native `.kigi` source for permission rules is `config.toml`, described in the section above.
Example:
@@ -223,7 +223,7 @@ Example:
}
```
Supported `defaultMode` values are `default`, `acceptEdits`, `bypassPermissions`, `dontAsk`, and `plan`. Grok reads `defaultMode` from its canonical location under `permissions`; a top-level `defaultMode` is also accepted when the nested key is absent.
Supported `defaultMode` values are `default`, `acceptEdits`, `bypassPermissions`, `dontAsk`, and `plan`. Kigi reads `defaultMode` from its canonical location under `permissions`; a top-level `defaultMode` is also accepted when the nested key is absent.
`permissions.allow`, `permissions.deny`, and `permissions.ask` entries are translated into native rules and then matched with the semantics in the [Rule Matching Reference](#rule-matching-reference). Translation notes:
@@ -250,7 +250,7 @@ Matching is case-sensitive. Leading whitespace in the command is trimmed before
A trailing `:*` suffix on a Bash rule is stripped to a plain prefix: `Bash(git commit:*)` becomes prefix `git commit`. Because prefixes have no word boundary, a `deny` written as `Bash(sed:*)` also blocks commands such as `sed-custom`.
**Chained commands.** Grok parses each command like a shell and splits it on `&&`, `||`, `;`, `|`, and newlines. The rule actions treat segments differently:
**Chained commands.** Kigi parses each command like a shell and splits it on `&&`, `||`, `;`, `|`, and newlines. The rule actions treat segments differently:
- `deny` and `ask` rules are checked against every segment, and against the whole string. One denied segment rejects the entire command.
- `allow` rules are checked against the whole command string only. `Bash(git *)` therefore auto-approves `git status && rm -rf /`, because the full string starts with `git `. Pair narrow allow rules with `deny` rules for the patterns you want to block.
@@ -277,7 +277,7 @@ Path patterns are globs matched against the path string the tool was called with
### MCP Rules
`MCPTool(...)` patterns match the full Grok tool name in `server__tool` form, with glob support: `MCPTool(linear__*)` matches every tool from the `linear` server. Grok tool names carry no `mcp__` prefix, so a rule written as `mcp__server__tool` never matches an MCP call; write `MCPTool(server__tool)` instead.
`MCPTool(...)` patterns match the full Kigi tool name in `server__tool` form, with glob support: `MCPTool(linear__*)` matches every tool from the `linear` server. Kigi tool names carry no `mcp__` prefix, so a rule written as `mcp__server__tool` never matches an MCP call; write `MCPTool(server__tool)` instead.
### WebFetch Rules
@@ -325,7 +325,7 @@ The remembered prefix is limited to a short form of the command: read-only comma
### Persistence Is Per Project
Interactive grants are stored in Grok's own state directory under your home directory, scoped to the directory you launched Grok from. A grant made in one project never applies in another, grants are not written into the repository, and they are not meant to be hand-edited.
Interactive grants are stored in Kigi's own state directory under your home directory, scoped to the directory you launched Kigi from. A grant made in one project never applies in another, grants are not written into the repository, and they are not meant to be hand-edited.
Interactive grants are personal, per-machine state. For an allowlist you can review in code review and share with teammates, use declarative rules in the project's `.kigi/config.toml` instead.
@@ -411,7 +411,7 @@ For hook installation, the JSON format, the trust model for project hooks, and o
### Headless git and gh Only (CI and Automation)
```bash
grok -p "Implement the feature using only git and GitHub CLI" \
kigi -p "Implement the feature using only git and GitHub CLI" \
--allow 'Read' \
--allow 'Grep' \
--allow 'Bash(git *)' \
@@ -12,7 +12,7 @@ which already shows when work is in flight.
Three entry points, all opening the same view:
- **`grok dashboard`** — launches the TUI directly into the dashboard.
- **`kigi dashboard`** — launches the TUI directly into the dashboard.
- **`/dashboard`** (aliases **`/agents-dashboard`**, **`/sessions`**) — open
from inside an active session.
- **Ctrl+\\** — same as the slash command, two keystrokes. Configurable
@@ -23,7 +23,7 @@ Three entry points, all opening the same view:
## What you see
```
Grok Build · Dashboard — 4 agents · 2 awaiting
Kigi · Dashboard — 4 agents · 2 awaiting
▌● reviewer · audit token flow Awaiting your input 2m
● implementer · fix login bug Running: cargo test 12m
⋅ refactor · feat/login Responding… 24m
@@ -51,7 +51,7 @@ bottom of the group; select it and press `Enter` / `→` (or click it) to
reveal them all, and `←` to re-fold. The Idle header always shows the true total. Folding is
suspended while a filter or search is active (so every match shows).
The state icon matches Grok Build's sibling views (
The state icon matches Kigi's sibling views (
`tasks_pane`):
- `⋅`/`:`/`⸬`/`⁙` — animated spinner for **Working** rows.
@@ -346,6 +346,6 @@ friendly toast.
## Phase 4 (out of scope for v1)
The current dashboard lists only agents owned by **this** pager
process. The plan's Phase 4 ("supervisor / `grok --bg`") would list
process. The plan's Phase 4 ("supervisor / `kigi --bg`") would list
sessions that survive pager exit — that's a separate roadmap and not
shipped yet.
@@ -1,10 +1,10 @@
# Monitoring Usage (External OpenTelemetry)
> **Status: alpha.** The schema below is versioned (`grok_code.schema.version = v1`);
> **Status: alpha.** The schema below is versioned (`kigi_code.schema.version = v1`);
> additive changes may occur without notice, renames/removals will bump the
> version and be called out in the changelog.
Grok CLI can export usage **metrics** and **events** to your organization's
Kigi CLI can export usage **metrics** and **events** to your organization's
own OpenTelemetry collector, so platform teams can monitor adoption, token
consumption, tool-permission decisions, and errors across the fleet — without
any data flowing through SpaceXAI.
@@ -32,7 +32,7 @@ export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf # or grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=https://collector.corp.example:4318
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <collector-token>"
grok
kigi
```
`KIGI_EXTERNAL_OTEL=1` alone enables **nothing** — you must also select at
@@ -56,7 +56,7 @@ without the master switch.
| `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` | `delta` | `delta` \| `cumulative`. |
| `OTEL_METRICS_INCLUDE_SESSION_ID` | `1` | Attach `session.id` to metrics (cardinality opt-out). |
| `OTEL_METRICS_INCLUDE_VERSION` | `0` | Attach `app.version` to metrics. |
| `OTEL_LOG_USER_PROMPTS` | `0` | Content gate: prompt text on `grok_code.user_prompt` (60 KB cap, secret-scrubbed). |
| `OTEL_LOG_USER_PROMPTS` | `0` | Content gate: prompt text on `kigi_code.user_prompt` (60 KB cap, secret-scrubbed). |
| `OTEL_LOG_TOOL_DETAILS` | `0` | Content gate: tool parameters (4 KB cap), full file paths, verbatim MCP/skill/plugin names. Bash command text is **never** exported in v1, even with this gate. |
`OTEL_RESOURCE_ATTRIBUTES` is deliberately ignored: the resource is built
@@ -95,7 +95,7 @@ There is deliberately no `headers` key: supply collector auth via
`OTEL_EXPORTER_OTLP_HEADERS` so tokens are never stored on disk.
Managed deployments can additionally enable org-wide telemetry by distributing
the `[telemetry]` `otel_*` keys through `grok setup` managed config /
the `[telemetry]` `otel_*` keys through `kigi setup` managed config /
requirements pins, or force-disable it fleet-wide with the same local config
layers (`external_otel_disabled`, content-gate locks).
@@ -103,29 +103,29 @@ layers (`external_otel_disabled`, content-gate locks).
| Attribute | Value |
|---|---|
| `service.name` | `grok-cli` |
| `service.name` | `kigi-cli` |
| `service.version`, `client.version` | build/client versions |
| `app.entrypoint` | `cli` \| `headless` \| `agent` |
| `terminal.type` | terminal emulator brand |
| `grok_code.schema.version` | `v1` |
| `kigi_code.schema.version` | `v1` |
Identity attributes (`user.id`, and `organization.id` / `team.id` /
`deployment.id` when known) are attached per metric data point and per event
once authentication completes. `prompt.id` (per-prompt UUID) appears on
events only, never metrics.
## Metrics (meter scope `ai.xai.grok_code`)
## Metrics (meter scope `ai.xai.kigi_code`)
| Metric | Unit | Attributes |
|---|---|---|
| `grok_code.session.count` | `{session}` | base attrs only |
| `grok_code.token.usage` | `{token}` | `type` = `input` \| `output` \| `reasoning` \| `cache_read`; `model` |
| `grok_code.turn.count` | `{turn}` | `outcome` = `completed` \| `cancelled` \| `error`; `model` |
| `grok_code.tool.decision` | `{decision}` | `tool_name`, `decision` = `allow` \| `deny` \| `cancelled` \| `followup`, `access_kind`, `permission_mode` |
| `grok_code.tool.usage` | `{call}` | `tool_name`, `outcome` |
| `grok_code.error.count` | `{error}` | `error_category`, `model` |
| `kigi_code.session.count` | `{session}` | base attrs only |
| `kigi_code.token.usage` | `{token}` | `type` = `input` \| `output` \| `reasoning` \| `cache_read`; `model` |
| `kigi_code.turn.count` | `{turn}` | `outcome` = `completed` \| `cancelled` \| `error`; `model` |
| `kigi_code.tool.decision` | `{decision}` | `tool_name`, `decision` = `allow` \| `deny` \| `cancelled` \| `followup`, `access_kind`, `permission_mode` |
| `kigi_code.tool.usage` | `{call}` | `tool_name`, `outcome` |
| `kigi_code.error.count` | `{error}` | `error_category`, `model` |
There is no `cost.usage` metric: join `grok_code.token.usage` with your own
There is no `cost.usage` metric: join `kigi_code.token.usage` with your own
price sheet. `lines_of_code.count` and `active_time.total` are planned for a
later phase.
@@ -143,23 +143,23 @@ active.
| `event.name` | Attributes |
|---|---|
| `grok_code.session_start` | `model`, `permission_mode`, `mcp_server_count`, `plugin_count`, `skill_count`, `hook_count`, `memory_enabled`, `is_git_repo`, `client_identifier` |
| `grok_code.session_end` | `duration_secs`, `turn_count`, `tool_call_count`, `compaction_count`, `model` |
| `grok_code.user_prompt` | `prompt_length`, `model`, `screen_mode?` (`fullscreen` \| `inline` \| `minimal` \| `headless` \| `other`); `prompt` (**prompts**) |
| `grok_code.turn_completed` | `outcome`, `duration_ms`, `tool_call_count`, `model`, `error_category?`, `cancellation_category?` |
| `grok_code.api_request` | `model`, `duration_ms`, `stop_reason?`, `input_tokens`, `output_tokens`, `reasoning_tokens`, `cache_read_tokens` |
| `grok_code.api_error` | `error_category`, `model`, `status_code?`, `duration_ms?` |
| `grok_code.tool_result` | `tool_name`, `outcome`, `success`, `duration_ms`, `file_extension`; `tool_parameters`, `file_path` (**details**) |
| `grok_code.tool_decision` | `tool_name`, `decision`, `access_kind`, `permission_mode`, `source` |
| `grok_code.mcp_server_connection` | `status`, `transport_type`, `duration_ms`, `tool_count?`, `error_type?`; `mcp_server.name` (**details**; collapsed to `mcp_server` otherwise) |
| `grok_code.permission_mode_changed` | `to_mode`, `trigger` |
| `grok_code.skill_activated` | `skill_source`; `skill.name` (**details**) |
| `grok_code.plugin_loaded` | `install_kind?`, `success`, `error_category?`; `plugin_name` (**details**) |
| `grok_code.compaction` | `duration_ms`, `tokens_before`, `tokens_after`, `model?` |
| `grok_code.subagent` | `phase` = `launched` \| `completed`, `subagent_type?`, `outcome?`, `duration_ms?` |
| `grok_code.auth` | `auth_method` |
| `grok_code.internal_error` | `error_type` (class only — no message, no location) |
| `grok_code.model_switched` | `from_model`, `to_model`, `success`, `error_code?` |
| `kigi_code.session_start` | `model`, `permission_mode`, `mcp_server_count`, `plugin_count`, `skill_count`, `hook_count`, `memory_enabled`, `is_git_repo`, `client_identifier` |
| `kigi_code.session_end` | `duration_secs`, `turn_count`, `tool_call_count`, `compaction_count`, `model` |
| `kigi_code.user_prompt` | `prompt_length`, `model`, `screen_mode?` (`fullscreen` \| `inline` \| `minimal` \| `headless` \| `other`); `prompt` (**prompts**) |
| `kigi_code.turn_completed` | `outcome`, `duration_ms`, `tool_call_count`, `model`, `error_category?`, `cancellation_category?` |
| `kigi_code.api_request` | `model`, `duration_ms`, `stop_reason?`, `input_tokens`, `output_tokens`, `reasoning_tokens`, `cache_read_tokens` |
| `kigi_code.api_error` | `error_category`, `model`, `status_code?`, `duration_ms?` |
| `kigi_code.tool_result` | `tool_name`, `outcome`, `success`, `duration_ms`, `file_extension`; `tool_parameters`, `file_path` (**details**) |
| `kigi_code.tool_decision` | `tool_name`, `decision`, `access_kind`, `permission_mode`, `source` |
| `kigi_code.mcp_server_connection` | `status`, `transport_type`, `duration_ms`, `tool_count?`, `error_type?`; `mcp_server.name` (**details**; collapsed to `mcp_server` otherwise) |
| `kigi_code.permission_mode_changed` | `to_mode`, `trigger` |
| `kigi_code.skill_activated` | `skill_source`; `skill.name` (**details**) |
| `kigi_code.plugin_loaded` | `install_kind?`, `success`, `error_category?`; `plugin_name` (**details**) |
| `kigi_code.compaction` | `duration_ms`, `tokens_before`, `tokens_after`, `model?` |
| `kigi_code.subagent` | `phase` = `launched` \| `completed`, `subagent_type?`, `outcome?`, `duration_ms?` |
| `kigi_code.auth` | `auth_method` |
| `kigi_code.internal_error` | `error_type` (class only — no message, no location) |
| `kigi_code.model_switched` | `from_model`, `to_model`, `success`, `error_code?` |
## Privacy model
@@ -213,14 +213,14 @@ Example queries (PromQL, with the Prometheus exporter above):
```promql
# Tokens by model and type across the org, 1h rate
sum by (model, type) (rate(grok_code_token_usage_total[1h]))
sum by (model, type) (rate(kigi_code_token_usage_total[1h]))
# Sessions per team per day
sum by (team_id) (increase(grok_code_session_count_total[1d]))
sum by (team_id) (increase(kigi_code_session_count_total[1d]))
# Tool-permission denial ratio
sum(rate(grok_code_tool_decision_total{decision="deny"}[1h]))
/ sum(rate(grok_code_tool_decision_total[1h]))
sum(rate(kigi_code_tool_decision_total{decision="deny"}[1h]))
/ sum(rate(kigi_code_tool_decision_total[1h]))
```
## Debugging
@@ -1,6 +1,6 @@
# Grok Build User Guide
# Kigi User Guide
Learn how to install, configure, and extend Grok Build, the terminal-based AI coding assistant from SpaceXAI.
Learn how to install, configure, and extend Kigi, the terminal-based AI coding assistant from SpaceXAI.
---
@@ -20,7 +20,7 @@ Start here. These guides cover what you need on your first day.
## Tier 2: Core Feature Docs
Customize and extend Grok Build.
Customize and extend Kigi.
| # | Document | Description |
|---|----------|-------------|
@@ -37,11 +37,11 @@ Customize and extend Grok Build.
## Tier 3: Advanced Usage Docs
Automate, script, and integrate Grok Build with other systems.
Automate, script, and integrate Kigi with other systems.
| # | Document | Description |
|---|----------|-------------|
| 14 | [Headless Mode and Scripting](14-headless-mode.md) | `grok -p`, output formats, CI/CD integration, and piping |
| 14 | [Headless Mode and Scripting](14-headless-mode.md) | `kigi -p`, output formats, CI/CD integration, and piping |
| 15 | [Agent Mode and IDE Integration](15-agent-mode.md) | ACP stdio transport, WebSocket relay, and SDK integration |
| 16 | [Subagents and Personas](16-subagents.md) | Parallel child sessions, agent types, personas, and capability modes |
| 17 | [Session Management](17-sessions.md) | Save, load, resume, rewind, compact, and the session persistence format |