Hard fork of xai-org/grok-build (Apache-2.0) re-targeted as Kigi, an
unofficial Kimi Code CLI community build.
Rename & identity
- 72 xai-*/xai-grok-* crates -> kigi-* (explicit: xai-grok-pager-bin ->
kigi-bin [binary `kigi`], xai-grok-pager -> kigi-tui; rest mechanical);
ptyctl, ptyctl-cli, third_party/ unchanged; proto package
xai.grok.tools.v1 -> kigi.tools.v1
- Config home ~/.kigi (KIGI_SHARE_DIR override), env prefix GROK_* ->
KIGI_*, `kigi --version` carries the unofficial-community-build notice
- clap identity, help text, startup banner, prompt templates rebranded
(templates re-encrypted)
Deletions (PRD removal list #5/#6/#7/#9/#10)
- voice input (xai-grok-voice) and all TUI wiring
- telemetry: Mixpanel client, external OTel stream, Sentry, OTLP layers,
trace/GCS/S3 upload queues (kigi-file-utils halved), workspace upload
module & dc_log, heap-profile uploader, auth-diagnostics uploader,
session-analytics halves of feedback; local zero-egress observability
preserved in new kigi-log crate (unified log, --debug firehose,
subsystem file logs, opt-in instrumentation)
- announcements (crate, remote-settings fields, TUI surfaces)
- plugin marketplace (crate, sources/browse/CTA/extensions-modal tab);
direct plugin install/uninstall/update via kigi-agent git_install kept
- relay/gateway/assets endpoints and features (agent relay, headless
relay transport, gateway bridge, LeaderEnvUrls); leader IPC socket now
~/.kigi/leader.sock + KIGI_LEADER_SOCKET, no ws-url derivation
- functional types rehomed instead of deleted: PermissionMode ->
kigi-config-types, McpInitStrategy -> kigi-mcp, PrCreationSource ->
session signals, TerminalDiagnostics -> kigi-pager-render, agent_id ->
shell util
Endpoints
- kigi-env rewritten: single production KigiEndpoints {coding_api_base_url
https://api.kimi.com/coding/v1 (KIGI_CODE_BASE_URL), oauth_host
https://auth.kimi.com (KIGI_OAUTH_HOST), update_base_url (GitHub
Releases API), upgrade_page_url}; GrokBuildEnvironment enum deleted
Toolchain & workspace hygiene
- Rust 1.97.0 pinned; edition 2024; full cargo update; git2 hoisted to
workspace at 0.21 (Option->Result API migration), quick-xml 0.41
- Root Cargo.toml hand-maintained (PRD §8.1): version 0.1.0 inherited by
all members, members sorted, unused deps pruned
- cargo-deny advisories gate (deny.toml with documented transitive
exceptions); CI workflow (check/clippy/fmt/deny/test, macOS+Linux)
- cross-crate test seams re-gated behind `test-support` cargo feature;
insta snapshot baselines renamed to the kigi_tui prefix
- clippy --workspace --all-targets: zero warnings; fmt clean
Fixes surfaced by the port
- updater probe/installer divergence (bin/kigi vs bin/grok symlink set)
- idle model-metadata refresh dead under KIGI_CODE_BASE_URL override
(new is_effective_coding_endpoint_url, loopback+override aware)
- macOS symlinked-TMPDIR fixture canonicalization (foreign_sessions,
fast-worktree); RSS measurement tests serialized via serial_test
Docs & legal (Apache §4)
- NOTICE added (upstream attribution + change statement); THIRD-PARTY
notices sustained; kigi-tools ported-code notices extended; README,
CONTRIBUTING, SECURITY, AGENTS.md rewritten
Out of scope for M0 (tracked): Kimi auth/inference (M1), search/fetch,
command parity, config import (M2), Computer Hub excision & final
brand-token sweep (M2), distribution & self-update rewrite (M3).
kigi-crash-handler
Crash handler for SIGBUS/SIGSEGV with best-effort backtrace capture.
How it works
install() registers a sigaction handler. On crash it writes a binary blob (GCRX format) to crash_dir/last-crash.bin and restores the terminal via pre-computed escape sequences. The handler uses only async-signal-safe operations for file I/O, terminal restore, and re-raise.
On next launch, check_previous_crash() reads the blob, resolves IPs to symbols via backtrace, writes last-crash-report.txt, and archives it (keeping the last 5 reports).
No-ops on non-unix platforms. On musl-based Linux (release builds), the handler still records signal/address/version but skips frame capture since musl does not provide backtrace().
Limitations
Frame capture is best-effort
Frame capture uses two fully async-signal-safe techniques:
- The crash instruction pointer is extracted directly from the
ucontext_tpassed by the kernel. - Additional frames are captured by walking the frame-pointer chain (RBP on x86_64, x29 on aarch64) with raw pointer reads.
In release builds without -C force-frame-pointers, the frame-pointer chain may be incomplete or empty (the compiler omits frame pointers by default for optimization). The crash PC is always captured. In debug/dev builds, frame pointers are retained by default, producing fuller call stacks.
sigaltstack is per-thread
The alternate signal stack is installed only on the thread that calls install(). Tokio worker threads do not inherit it. Stack overflows on worker threads will still trigger the handler (sigaction is process-wide), but without altstack protection the handler itself may fault on the overflowed stack.
Usage
use std::path::PathBuf;
let crash_dir = PathBuf::from("/home/user/.myapp/crash");
// check_previous_crash MUST be called before install(), because
// install() opens last-crash.bin with O_TRUNC.
if let Some(r) = kigi_crash_handler::check_previous_crash(&crash_dir) {
eprintln!("Crashed last session: {}", r.signal_name);
eprintln!("Report: {}", r.report_path.display());
}
// install() before any threads or async runtime — sigaltstack is per-thread.
// Creates crash_dir if it does not exist.
kigi_crash_handler::install(kigi_crash_handler::CrashHandlerConfig {
app_version: env!("CARGO_PKG_VERSION").to_string(),
crash_dir,
});