ZacharyZhang-NY 27d009cb6e fix(fs): Windows-safe atomic replace everywhere — model switch now sticks
Root cause of 'model+effort switch works on Mac, not on Windows': the
switch APPLIES in-session (the dispatch/apply chain is platform-identical,
verified adversarially) but its persistence never sticks on Windows.
Every tmp+rename atomic write except auth/storage.rs committed with a
bare fs::rename, and Windows MoveFileExW(REPLACE_EXISTING) fails with a
sharing violation whenever AV/search-indexer/cloud-sync transiently holds
the destination open. Consequences: [models].default never persisted
(next launch = original model), the session summary's current model never
persisted (resume = original model), and the models cache went silently
stale (all its write errors were swallowed).

- New kigi_shell_base::util::fs::replace_file — THE commit step for
  tmp+rename: plain rename on Unix; on Windows delete-first + two short
  backoffs (the pattern auth/storage.rs shipped first), tmp cleaned on
  failure, error always returned. Windows branch type-checked against
  x86_64-pc-windows-msvc.
- Adopted at every replace site: config.toml (save_config /
  atomic_write_string / mcp saves), models cache (plus unique tmp
  suffixes and tracing::warn on failure — writes were fully silent),
  session storage (summary/current-model, jsonl, plan/signals/
  announcement/goal/graph state), auth.json, active-sessions registry,
  prompt history, claude/kimi import, campaigns state, goal artifacts.
  Directory-move renames (worktree pool, corrupt-file backups) keep
  plain rename — their destinations don't pre-exist.

Verified: kigi-shell + kigi-shell-base 5318 tests green, clippy clean,
msvc-target check of the new cfg(windows) code clean.
2026-07-22 19:42:13 -04:00
2026-07-22 17:51:12 -04:00
2026-07-22 17:51:12 -04:00
2026-07-22 11:08:54 -04:00

Kigi (kigi) 🌘

🕸️ The world's first CLI with built-in Graph Engineering

/graph turns one objective into a dependency graph of autonomous, self-verifying agent loops — planned, parallelized, adversarially verified, and merged back, end to end.

Kigi is a coding agent that lives in your terminal. It reads the repo, writes the patch, runs the tests, and keeps going while you do something else. Full-screen, headless in CI with -p, or docked in your editor over ACP.

Already paying for Claude Pro/Max, ChatGPT Plus/Pro, GitHub Copilot, or Grok? Sign in and use it. No API key, no second bill. Rather bring your own key? OpenAI, Anthropic, Google, DeepSeek, Groq, Moonshot and two dozen more are wired in.

Installation · Graph engineering · Providers and API keys · Building from source · Coexistence with the official CLI · License

Kigi demo

Full-quality recording (mp4)


Installation

# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/ZacharyZhang-NY/Kigi-CLI/main/install.sh | bash
# Windows PowerShell
irm https://raw.githubusercontent.com/ZacharyZhang-NY/Kigi-CLI/main/install.ps1 | iex
kigi login   # pick a provider, sign in
kigi         # go

Single file, no runtime. macOS and Linux on arm64/x86_64, Windows on x86_64, checksummed against the release's SHA256SUMS. kigi update handles upgrades.

Graph engineering

Every other agent runs a loop: think, act, repeat — one thread, one thing at a time. /graph runs a dependency graph instead. Work that doesn't block other work happens at the same time, in separate worktrees, and nothing merges until something else has tried to tear it apart.

/graph <objective> [--budget <tokens>]   # decompose + run fully autonomously
/graph status                            # node tree, budget, current work
/graph show                              # box-drawing DAG view
/graph pause | resume [--budget <n>]     # halt / continue (budget top-up)
/graph clear                             # abandon the graph

One command runs the whole thing, start to finish:

  • A planner breaks your objective into a dependency DAG, then validates it.
  • Independent nodes fan out as parallel workers, each in its own git worktree.
  • Every node has to get past an adversarial verifier before it merges back.
  • Find something out of scope? Say DISCOVERED: and the graph replans — append-only, so nothing already agreed on gets rewritten.
  • Between passes, a topology optimizer drops dependencies that were never real.
  • A final node re-checks the whole objective before the graph is allowed to call itself done.

State lives in .kigi/graph.jsonl, next to your code. Close the laptop, come back tomorrow, /graph resume. A teammate can pick it up from the same file.

On by default. KIGI_GRAPH=0 turns it off; KIGI_GRAPH_CONCURRENCY (default 3) controls how many nodes run at once.

Providers and API keys

29 platforms ship compiled in: 5 you sign into, 24 you hand a key. Nothing is registered at runtime — if it's not in this list, it's not there.

Sign in with a subscription you already pay for. Run kigi login and pick. Each provider's token is stored under its own key, and one provider's credentials are never sent to another.

Platform id Provider Sign-in
kimi-code Kimi Code (original target) Subscription OAuth (device code)
claude-pro-max Claude Pro/Max Subscription OAuth (browser, PKCE)
openai-codex ChatGPT Plus/Pro (Codex) Subscription OAuth (browser, PKCE)
github-copilot GitHub Copilot Subscription OAuth (device code)
xai-grok xAI Grok Subscription OAuth (device code)

You get whatever models your plan actually serves — the list is fetched at sign-in, not hardcoded. (ChatGPT/Codex is the exception: its backend publishes no model endpoint, so those four are compiled in.)

API-key providers. Export the env var, or drop the key in ~/.kigi/config.toml. Keys are never logged.

Provider Platform id API key env
Moonshot (moonshot.cn) moonshot-cn KIGI_MOONSHOT_CN_API_KEY (or KIGI_MOONSHOT_API_KEY)
Moonshot (moonshot.ai) moonshot-ai KIGI_MOONSHOT_AI_API_KEY (or KIGI_MOONSHOT_API_KEY)
OpenAI openai OPENAI_API_KEY
Anthropic anthropic ANTHROPIC_API_KEY
DeepSeek deepseek DEEPSEEK_API_KEY
Groq groq GROQ_API_KEY
Mistral mistral MISTRAL_API_KEY
Fireworks AI fireworks FIREWORKS_API_KEY
Google Gemini google GEMINI_API_KEY
OpenRouter openrouter OPENROUTER_API_KEY
Together AI together TOGETHER_API_KEY
Cerebras cerebras CEREBRAS_API_KEY
NVIDIA NIM nvidia NVIDIA_API_KEY
Vercel AI Gateway vercel-ai-gateway AI_GATEWAY_API_KEY
xAI (Grok) xai XAI_API_KEY
Qwen Token Plan qwen-token-plan QWEN_TOKEN_PLAN_API_KEY
Qwen Token Plan (China) qwen-token-plan-cn QWEN_TOKEN_PLAN_CN_API_KEY
Kimi For Coding kimi-coding KIMI_API_KEY
Z.AI zai ZAI_API_KEY
Z.AI Coding (China) zai-coding-cn ZAI_CODING_CN_API_KEY
Xiaomi MiMo xiaomi XIAOMI_API_KEY
Xiaomi Token Plan (China) xiaomi-token-plan-cn XIAOMI_TOKEN_PLAN_CN_API_KEY
MiniMax minimax MINIMAX_API_KEY
MiniMax (China) minimax-cn MINIMAX_CN_API_KEY
export OPENAI_API_KEY=sk-...
export XAI_API_KEY=xai-...
# ~/.kigi/config.toml
[platforms.openai]
api_key = "sk-..."

[platforms.xai]
api_key = "xai-..."

Model lists sync on startup. Pick one with /model, set its thinking level with /effort.

Web search/fetch need a Kimi Code subscription; API-key sessions run without them, same as the official client.

Building from source

rustup toolchain install 1.97.0
cargo build --profile release-dist -p kigi-bin
./target/release-dist/kigi --version

protoc is invoked through the vendored dotslash launcher at bin/protoc; install dotslash (brew install dotslash or cargo install dotslash) if it is not already on your PATH.

Coexistence with the official Kimi CLI

Kigi started as an unofficial Kimi Code CLI — a community fork of xai-org/grok-build, not affiliated with Moonshot AI or xAI. It keeps its own binary, its own ~/.kigi, its own keyring entry, and its own KIGI_* env vars, and never touches what the official kimi CLI installed. kigi import-kimi copies your old config over once, read-only.

Zero telemetry. It talks to the APIs you configured, GitHub Releases, and your own MCP servers. Nothing else.

License

Apache-2.0. See LICENSE, NOTICE, and THIRD-PARTY-NOTICES. Code ported from openai/codex and sst/opencode is documented in crates/codegen/kigi-tools/THIRD_PARTY_NOTICES.md. Kigi is based on Grok Build Open Source; the --version output carries the attribution.

S
Description
Migrated from GitHub
Readme Apache-2.0
30 MiB
Languages
Rust 99.7%
Python 0.3%