* feat(config): add env overrides for loop control and background task limits
Add three operational environment overrides, resolved as env > config.toml
> default in both engines (agent-core and agent-core-v2), matching the
existing KIMI_IMAGE_MAX_EDGE_PX / KIMI_SUBAGENT_TIMEOUT_MS pattern:
- KIMI_LOOP_MAX_STEPS_PER_TURN overrides loop_control.max_steps_per_turn
- KIMI_LOOP_MAX_RETRIES_PER_STEP overrides loop_control.max_retries_per_step
- KIMI_CODE_BACKGROUND_MAX_RUNNING_TASKS overrides background.max_running_tasks
Invalid values are ignored and fall back to the config value. The v2 engine
resolves them through config section env bindings (effective-only, never
persisted); the v1 engine resolves them at the consumption point.
* fix(config): strip env-bound fields before persisting config writes
Environment overrides resolved into the effective config could be echoed
back through IConfigService.set/replace (e.g. GET then POST
/api/v1/config) and persisted into config.toml, outliving the env var.
This affected the pre-existing image / subagent / keep-alive bindings as
well as the new loop control and max-running-tasks bindings.
Extend ConfigStripEnv with a getEnv parameter and add a shared
stripEnvBoundFields helper: while a field's env var is set, writes
restore the field's raw on-disk value (or drop it) instead of persisting
an echoed env value; when unset, normal writes persist. Register it for
the loopControl, task/background, image, and subagent sections.
Also fix ConfigService.stripEnv looking up rawSnake by the camelCase
domain key; on-disk sections are keyed snake_case.
* fix(config): honor binding parsers when stripping env fields on persist
An invalid env value (e.g. KIMI_LOOP_MAX_STEPS_PER_TURN=abc) is ignored
on the read path but still marked the field env-owned on the write path,
so a config write for that field was silently dropped.
stripEnvBoundFields now derives the guard from the section's envBindings
and skips fields whose env value fails the binding's parse, so invalid
env values are ignored on both paths — and the duplicated field/env
descriptor list is gone.
Also drop function-level comments added beside helpers; agent-core-v2
keeps comments solely in the top-of-file block, so the strip semantics
now live in the config.ts / configService.ts headers.
* fix(config): re-apply env overlays from the env-free base on every read
Two follow-ups from review:
- ConfigService.get()/getAll() re-applied section env bindings on the
already-overlaid effective cache (and get() mutated it in place), so a
valid override degraded to invalid or unset kept serving the stale
value until the next reload — and an echoed stale value could then be
persisted by a config write. Reads now recompute from a cached
env-free validated base, so degraded or removed env values fall back
to the file immediately.
- stripEnvBoundFields restored env-owned fields from the raw snake
sub-object, missing values persisted under legacy keys (e.g.
max_steps_per_run). Section stripEnv now receives the env-free,
fromToml-normalized raw base, so legacy aliases are honored.
* test(kap-server): retry temp-home cleanup in auth tests
auth.test.ts removed its temp home with a plain recursive rm, which races
late async writers in the server shutdown path and flakes with ENOTEMPTY
(seen on main CI and locally on main). Harden the cleanup with the same
maxRetries/retryDelay options sessions.test.ts already uses.
* chore(changeset): consolidate the env-override changesets into two entries
One feature entry (loop/background env overrides, both engines plus the
CLI) and one fix entry (env values persisting on writes and sticking
after degrade/unset, agent-core-v2 plus the CLI).
* fix(config): clear fully-stripped sections and refresh overlay domains on get()
Two follow-ups from review:
- stripEnvBoundFields returned an empty object when every written field
was env-owned, so a section with a non-empty default (e.g. subagent)
stored raw = {} and the default stopped applying until the next
reload. A fully stripped result now clears the raw section instead.
- get(domain) only recomputed env overlays for sections with env
bindings, so domains written solely by a ConfigEffectiveOverlay
(models / defaultModel from KIMI_MODEL_NAME) kept serving stale cached
values after the env changed. get() now derives every non-memory
domain from the fresh env-free base, matching getAll().
* test(config): drive the get() overlay freshness test with an inline overlay
The previous version imported the model env overlay to activate it, which
the CI runners failed to resolve from this test file (both tsgo and
vitest, while the same specifier resolves elsewhere — not reproducible
locally). An inline ConfigEffectiveOverlay double exercises the same
ConfigService contract with a tighter seam and no module dependency.
* fix(config): preserve unknown fields on full strip and clone nested env targets
Two follow-ups from review:
- stripEnvBoundFields cleared the raw section whenever the stripped
result was empty, so an env echo write could drop unknown
forward-compatible fields from the TOML table. An emptied section now
keeps its raw table while the env-free base still holds other fields,
and is cleared only when nothing remains (defaults keep applying).
- applyEnvBindings reused nested child objects in place, so a nested
env binding on a persistable key would mutate the env-free validated
base and serve stale values after the env var is removed. Children
are now cloned before descending.
* fix(config): keep the env-free base when a strip leaves nothing to persist
Returning {} for a fully stripped write stored the empty object into the
raw layer while the TOML table survived via rawSnake, so the bases
diverged; a second echo write then saw an empty base, cleared the
section, and deleted the table — dropping unknown forward-compatible
fields. When nothing persistable remains, the write is now a no-op for
the section (the env-free base is kept as-is), and the section is
cleared only when the base is empty.
* fix(config): revalidate stripped results so restored raw values never persist
A strip may restore on-disk values from the unvalidated raw base (e.g.
an env-masked invalid field), smuggling them past the merge-time
validation into the stored config: the section would then fail the next
buildValidated pass, dropping accompanying valid edits from the runtime
while the invalid value stayed persisted. set() now revalidates the
stripped result — discarding the parse output so unknown fields survive
— and rejects the write instead, matching replace().
|
||
|---|---|---|
| .agents/skills | ||
| .changeset | ||
| .github | ||
| apps | ||
| build | ||
| docs | ||
| packages | ||
| plugins | ||
| scripts | ||
| .editorconfig | ||
| .gitattributes | ||
| .gitignore | ||
| .npmrc | ||
| .nvmrc | ||
| .oxfmtrc.json | ||
| .oxlintrc.json | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| CONTRIBUTING.md | ||
| flake.lock | ||
| flake.nix | ||
| GOAL.md | ||
| LICENSE | ||
| Makefile | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| README.zh-CN.md | ||
| SECURITY.md | ||
| tsconfig.json | ||
| vitest.config.ts | ||
Kimi Code CLI
Documentation · Issues · 中文
What is Kimi Code CLI
Kimi Code CLI is an AI coding agent that runs in your terminal — it can read and edit code, run shell commands, search files, fetch web pages, and choose the next step based on the feedback it receives. It works out of the box with Moonshot AI’s Kimi models and can also be configured to use other compatible providers.
Install
Install with the official script. No Node.js required.
- macOS or Linux:
curl -fsSL https://code.kimi.com/kimi-code/install.sh | bash
- Homebrew (macOS/Linux):
brew install kimi-code
- Windows (PowerShell):
irm https://code.kimi.com/kimi-code/install.ps1 | iex
On Windows, install Git for Windows before first launch because Kimi Code CLI uses the bundled Git Bash as its shell environment. If Git Bash is installed in a custom location, set
KIMI_SHELL_PATHto the absolute path ofbash.exe.
Then, run it with a new shell session:
kimi --version
For npm install, upgrade, uninstall, see Getting Started.
Quick Start
Open a project and start the interactive UI:
cd your-project
kimi
On first launch, run /login inside Kimi Code CLI and choose either Kimi Code OAuth or a Moonshot AI Open Platform API key. After login, try your first task:
Take a look at this project and explain its main directories.
Key Features
- Single-binary distribution. Install with one command: no Node.js setup, PATH gymnastics, or global module conflicts.
- Blazing-fast startup. The TUI is ready in milliseconds, so starting a session never feels heavy.
- Purpose-built TUI. A carefully tuned interface, optimized end to end for long, focused agent sessions.
- Video input. Drop a screen recording or demo clip into the chat and let the agent watch what is hard to describe in words — turn a reference clip into a LUT, a long video into a short, a screen recording into working code, and more.
- AI-native MCP configuration. Add, edit, and authenticate Model Context Protocol servers conversationally with
/mcp-config, without hand-editing JSON. - Rich plugin ecosystem. Install skills, MCP servers, and data sources from the marketplace or any GitHub repo, with each install's trust level surfaced up front.
- Subagents for focused, parallel work. Dispatch built-in
coder,explore, andplansubagents in isolated contexts while keeping the main conversation clean. - Lifecycle hooks. Run local commands at key points to gate risky tool calls, audit decisions, trigger desktop notifications, or connect to your own automation.
- Editor & IDE integration (ACP). Drive a Kimi Code CLI session straight from Zed, JetBrains, or any Agent Client Protocol client with
kimi acp.
Use it in your editor (ACP)
Kimi Code CLI speaks the Agent Client Protocol, so ACP-compatible editors and IDEs (Zed, JetBrains, …) can drive a session over stdio. Log in once, then point your editor at the kimi acp subcommand — no extra login needed.
For Zed, add this to ~/.config/zed/settings.json:
{
"agent_servers": {
"Kimi Code CLI": {
"type": "custom",
"command": "kimi",
"args": ["acp"],
"env": {}
}
}
}
Then open a new conversation in Zed's Agent panel. See Using in IDEs for JetBrains setup and troubleshooting, and the kimi acp reference for the full capability matrix.
Docs
- Getting Started
- Interaction and approvals
- Sessions
- Using in IDEs (ACP)
- Configuration
- Command reference
Develop
Requirements: Node.js ≥ 24.15.0, pnpm 10.33.0.
git clone https://github.com/MoonshotAI/kimi-code.git
cd kimi-code
pnpm install
pnpm dev:cli # run the CLI in dev mode
pnpm test # run tests
pnpm typecheck # TypeScript check
pnpm lint # oxlint
pnpm build # build all packages
See CONTRIBUTING.md for the full contribution guide.
Community
- Issues
- For security vulnerabilities, see SECURITY.md.
Acknowledgements
Our TUI is built on top of pi-tui. We thank the authors of pi-tui for their valuable work.
License
Released under the MIT License.
