§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
@@ -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.