kimi-code/docs/zh/reference/kimi-command.md
liruifengv 8c865f4817
feat(kimi-code): support automatic updates for native installations via staged swap (#2994)
* feat(kimi-code): support automatic updates for native installations via staged swap

Native (SEA) installs previously could not self-update on Windows and
relied on 'curl | bash' re-install on Unix. Replace both with a staged
swap updater:

- startup swaps in a staged binary (verified against the release
  manifest sha256, smoke-checked via --version) and re-execs it, so the
  running process never replaces itself (Windows-safe)
- downloads run in a self-spawned hidden sub-command, in the background
  from the update preflight or in the foreground from 'kimi upgrade'
- rollback from .bak on any swap failure; install failures keep the
  existing retry/prompt thresholds

* fix(kimi-code): fully clean staged artifacts on swap discard paths

Real-binary smoke testing on macOS surfaced two cleanup gaps in the
discard path: the claimed metadata file was unlinked after the staging
dir rmdir (so the empty dir survived), and the staged exe was
rediscovered via the already-claimed staged.json (so it leaked on the
downgrade-guard path). Pass the known metadata through and order the
unlink before the rmdir.

* fix(kimi-code): restore staged metadata on swap failure and sweep update leftovers at startup

* fix(kimi-code): address codex review on lock contention and swap crash window

- The background native install no longer takes the outer install lock:
  the self-spawned downloader holds it for the whole download, and the
  parent's spawn-time lock raced the child into a false lastSuccess.
- Smoke-check the staged exe before moving anything, so a bad staged
  binary is discarded with the install path never left empty; the
  remaining crash window is two adjacent atomic renames (documented,
  recoverable via the .bak or by re-running the install script).

* test(kimi-code): align swap test expectation with smoke-before-rename order

The restore-on-failure case now observes the early smoke check's
--version spawn; only the re-exec spawn must be absent.

* fix(kimi-code): stage the bare CDN binary instead of unzipping

The published per-release artifacts are the bare platform binaries
(kimi-code-<target>[.exe]), not zip archives — the staging flow now
streams the download straight to the staged exe after the manifest
sha256 check, and the zip reader is dropped. Verified end-to-end on
macOS against the live CDN: download -> sha256 match -> swap ->
re-exec into the real released binary.

* fix(kimi-code): address second codex review round

- re-exec: forward 128 + signo when the swapped-in child dies by signal
  instead of reporting exit 0
- __update_download: only exit 0 without staging when the lock holder is
  staging the SAME version; a different in-flight version (or a vanished
  lock) no longer surfaces as a successful foreground upgrade
- staging: sweep orphaned .part downloads and unreferenced staged exes
  before downloading, preserving live swap claims and their payloads

* feat(kimi-code): show download progress for native updates

The foreground 'kimi upgrade' path streamed 180 MB with a single static
'Downloading…' line. Render progress instead: a throttled in-place
percentage line on a TTY, one line per 32 MB when piped, and plain MB
counts when Content-Length is unknown.

* fix(kimi-code): bound native update downloads with an idle timeout

Codex review: the manifest fetch cleared its timer once headers arrived,
so a stalled response body hung the worker forever, and the binary
download had no abort at all. The manifest timeout now covers body
consumption, and the binary stream aborts after 30 s without a chunk
(total duration stays unbounded for slow networks). The idle timeout is
injectable for tests.

* fix(kimi-code): retry native updates blocked by an orphaned active record

Windows real-machine verification surfaced that a parent exiting before
the downloader's exit event leaves a fresh-looking 'active' record that
silently blocks every background retry for the 6 h TTL. For native
installs, lock liveness is the truth past a 60 s spawn grace window:
a held lock means a download is running, a free lock means the record
is an orphan and a new attempt may start. Package-manager sources keep
the TTL behavior (no lock to prove liveness).

* fix: skip staged swap while another instance holds a fresh claim

sweepStaleNativeUpdateArtifacts already detected an in-progress swap in
a concurrent instance, but the result stayed inside the cleanup helper:
startup still claimed a newly published staged.json and ran a second
swap, so the two launchers could rename the install path and delete each
other's rollback backup. Propagate the in-progress signal and skip
claiming until the existing claim is released or goes stale.

* fix: keep the install lock while its holder process is alive

The install lock went stale purely by age (30 min), but the native
downloader is idle-bounded, not duration-bounded: a slow link can
legitimately take longer. Another startup would then sweep the lock and
spawn a second downloader, and both would write and clean the same
.staging paths. Past the age threshold, fall back to a pid liveness
probe (signal 0) — the lock is stale only when the holder is gone.

* fix: keep recovery artifacts on rollback failure and wait out same-version downloads

Two robustness fixes from review:

- native-swap: when moving the staged exe into place fails AND the
  rollback rename fails too (transient lock, AV), the install path is
  left absent and no next launch can start. Discarding the staged
  payload and claim on top of that removes the second recovery copy.
  rollback() now reports its result; on a double failure the swap keeps
  the .bak (which IS the old exe), the staged exe and the claim so
  manual recovery or a re-install still works.
- update-download: a foreground `kimi upgrade` racing a background
  downloader of the same version exited 0 immediately, so the CLI
  printed a success message for a download that could still fail. The
  worker now waits while the same-version holder is in flight, adopts
  the verified staged result (staged.json lands before the lock is
  released), and takes over the download when the holder finished
  without staging.

* fix: stamp the swap claim with a fresh mtime when claiming

rename() preserves the staged metadata's mtime, which can be arbitrarily
old — the background download often finishes hours before the next
launch claims it. A concurrent launch's sweep would then classify the
live claim as crash residue (older than the 5-minute window) and delete
the claim, the staged exe, and eventually the first swap's rollback
backup. Stamp the claim file with the claim time so the staleness check
measures the swap's liveness, not the download's age.

* fix: stamp the claim before the rename so it is born fresh

Stamping after the rename left a window: a concurrent launch could
inspect the claim between the two syscalls, see the staged metadata's
old mtime, and delete the staged executable mid-swap. utimes the state
file first so the claim carries a fresh timestamp from the instant it is
published — no fresh-looking-later intermediate state exists.

* fix: chmod the staged download before publishing it at its final name

A swap claims only the staged METADATA; the staged exe stays in
.staging/. A concurrent same-version downloader (possible because swaps
do not hold the install lock) then re-downloads and renames its .part
over that path. If the swap moves the file into the install path between
the downloader's rename and its post-publish chmod, the chmod lands on a
path that is already gone and the installation is left non-executable —
every future launch fails. Apply the executable mode to the private
.part file before the publishing rename so the staged exe is executable
from the instant it appears.

* fix: publish the install lock atomically via hard link

The 'wx' open exposed a momentarily empty lock file before its contents
were written. A concurrent acquirer reading in that window got a
SyntaxError, treated the lock as stale, swept it and also won — two
"holders" then ran stageNativeUpdate against the same .staging paths.
Write the lock contents to a unique temp file and hard-link it into
place: link() fails when the destination exists (same exclusivity as
'wx') and the lock path only ever appears fully written.

* fix: serialize stale-lock takeover through a secondary lock

A pathname-level delete can never be conditioned on the file still being
the inspected stale instance, so a plain compare-and-delete still loses
exclusivity: two workers classifying the same stale lock could interleave
unlink and publish such that both won (proven by a 20-way contention
test). Takeovers now go through a secondary create-if-absent lock
(install.lock.takeover): the delete+publish section only ever runs in
one process, staleness is re-validated inside it, and a fast-path creator
that wins the briefly-free path simply beats the takeover. The takeover
lock itself is age-swept (a live section lasts microseconds), and handles
only release the lock instance they own.

* fix: verify lock ownership after publish and preserve freshly staged exes

Two more race fixes from review:

- install-lock: the stale-marker sweep repeats the inspect-then-delete
  race one level up — two contenders sweeping the same aged takeover
  marker could both win and enter the main-lock section together.
  Pathname APIs offer no conditional delete, so both the takeover marker
  and the main lock now verify ownership after publishing (unique marker
  content, read-back compare): a racing sweep converts to a single
  survivor instead of two holders. The irreducible residual (a delete
  landing in the microsecond link-to-verify window) degrades to a wasted
  download cycle, never a corrupt install — swap claims guard the exe
  independently.
- native-swap: sweeping a stale swap claim deleted the exe it referenced
  even when a FRESH staged.json referenced the same version-derived name
  (a downloader re-staged the version after the swap crashed), throwing
  away a verified ~180 MB stage. The sweep now preserves any exe the
  current staged metadata still references.

* fix: reject mismatched manifests, take over from dead holders, unique .part names

Three robustness fixes from review:

- native-manifest: the per-release endpoint can answer with ANOTHER
  release's manifest (stale cache, mispublish); its checksums would then
  be applied to this version's binary and fail verification on every
  attempt. Compare the parsed manifest version with the requested one.
- install-lock/update-download: a killed lock holder skips its finally
  and never releases, stranding a waiting foreground `kimi upgrade`
  forever. A lock whose recorded pid is dead is now stale at any age
  (the atomic publish guarantees the pid was alive when written), and
  the same-version wait loop polls the acquisition itself, so a dead
  holder's lock is taken over within one poll instead of never.
  Package-manager spawns are unaffected: they hold the lock only around
  the spawn, and the active-record bookkeeping guards that layer.
- native-stage: the download intermediate is now unique per worker
  (`.part` carries pid + counter), so overlapping same-version workers
  can no longer interleave writes into the same file.

* fix: restrict staging cleanup to updater-owned names and retry short writes

- cleanupStagingOrphans recursively deleted anything it did not
  recognize; the staging dir sits next to the exe and can contain files
  belonging to the user or another tool. Deletion now requires a
  positive match on updater-owned artifact names (staged exes and .part
  intermediates) and only ever unlinks files.
- FileHandle.write may persist fewer bytes than requested (short write,
  e.g. near disk exhaustion) while the running hash and size already
  accounted for the whole chunk — publishing a truncated binary under a
  valid checksum. The chunk write now loops until fully persisted.

* fix: scope failure cleanup, recognize all semvers, reverify staged checksums

Three fixes from review:

- native-stage failure cleanup deleted whatever staged update was
  currently published — including a concurrent worker's valid result
  that its caller had already reported as success. The catch path now
  removes only this attempt's own artifacts: its unique .part file and
  its staged exe name when the current metadata does not reference it.
- The orphan-cleanup ownership check only matched stable x.y.z names;
  prerelease/build-metadata versions (1.2.3-rc.1, 1.2.3+build) would
  never be cleaned and accumulate ~180 MB each. Ownership now derives
  from the semver contract via the semver package's valid().
- The swap path trusted a staged exe whose size matched, though the
  metadata records the release checksum; post-download on-disk damage
  could pass the --version smoke check with corrupted bytes.
  claimStagedUpdate now re-verifies the staged exe's sha256 before
  claiming and discards the stage (for a later re-download) on mismatch
  — paid only when an update is actually pending.

* fix: validate versions before path derivation and honor the update opt-out in the swap

- native-stage: stageNativeUpdate derived staging paths (including the
  cleanup rm targets) from the version before fetchNativeReleaseManifest
  rejected it; a traversal string like `x/../../kimi` would resolve the
  staged-exe cleanup onto the running installation. The semver check now
  happens before any path is derived, and the staged-metadata schema
  constrains exeFileName to a plain file name.
- native-swap: the startup swap ran before the update preflight, so
  KIMI_CODE_NO_AUTO_UPDATE / KIMI_CLI_NO_AUTO_UPDATE stopped gating
  update behavior once a payload was pending. The swap now honors the
  same opt-out: the staged payload stays in place for a later launch
  without the variable, and the current exe starts.

* fix: restrict backup cleanup to updater-owned .bak names

cleanupBackups treated every <exe>.*.bak sibling as swap residue, so a
user's own backup like kimi.config.bak in a shared bin directory was
silently deleted on startup. Only the exact <exe>.bak and the numeric
PID fallback <exe>.<pid>.bak are updater-created — cleanup now
positively matches those two formats.

* fix: claim staged metadata before validating it and let manual upgrades bypass the opt-out

- native-swap: claimStagedUpdate validated the metadata and hashed the
  staged exe BEFORE the atomic rename, so a concurrent downloader
  superseding staged.json in between could get its fresh metadata
  claimed under the older object — the smoke check then failed and
  discard() deleted the newly published stage, recording a failure for
  the wrong version. The claim (utimes + rename) now happens first and
  validation acts on exactly the claimed file; discards use a new
  discardClaimedUpdate that never removes anything a meanwhile-published
  stage references.
- The auto-update env opt-out gated the startup swap unconditionally,
  so an explicit `kimi upgrade` with the variable set staged the
  version but no launch ever applied it. Stages now record
  `manual: true` when they answer a user-initiated install
  (`__update_download --manual`, threaded from installUpdate through
  the hidden sub-command), and the swap applies manual stages even when
  automatic updates are opted out.

* fix: promote adopted stages to manual and preserve claim-referenced payloads

Three follow-up fixes from review:

- An explicit `kimi upgrade` adopting an auto-staged payload (already
  on disk, or still downloading via the wait path) returned before the
  manual marker applied, so under the env opt-out the swap still skipped
  it despite the success message. Both adoption paths now promote the
  staged metadata to manual: true via a new promoteStagedUpdateToManual.
- The download-failure cleanup checked only the current staged metadata,
  but a live swap holds the metadata renamed aside as its claim — a
  failing same-version downloader could delete the exe an active swap
  was about to move into place. The catch path now also preserves names
  referenced by any live swap claim.
- Restoring a claimed stage after a failed exe move used rename, which
  on POSIX replaces a newer staged.json a downloader published during
  the smoke check. The restore is now a create-if-absent hard link: it
  only lands when the state-file path is still free, and the older claim
  is discarded when a newer stage has taken it.

* fix: drop exe deletion from stale-claim cleanup

The stale-claim sweep deleted the referenced exe based on a metadata
snapshot taken before the loop; a downloader republishing the same
version between the read and the unlink would have its fresh payload
deleted after reporting success. Publication can never be synchronized
with a pathname-level snapshot, so the sweep now removes only the claim
files themselves — genuinely unreferenced exes are reaped by the
downloader's own orphan cleanup (keep-set aware) before its next stage.

* fix: never delete the staged exe when discarding a claim

The same publication race existed one level down: a same-version
downloader can rename its fresh payload onto the shared exe path after
the discard's metadata snapshot but before the unlink (payloads publish
before their metadata), and the discard would delete a download whose
caller then reports success with nothing behind it. discardClaimedUpdate
now removes only the claimed metadata file; unreferenced exes are reaped
by the downloader's own orphan cleanup before its next stage.

* fix: only reap staging orphans old enough to be abandoned

The orphan sweep could delete a concurrent worker's freshly renamed
staged exe in the gap before its staged.json lands (payloads publish
before their metadata), turning the admitted duplicate-worker race into
a successful stage with no payload behind it. Unreferenced artifacts are
now only deleted once older than a one-hour grace period — publication
takes milliseconds, so unreferenced AND old means definitively
abandoned.

* fix: honor the persisted auto-update preference in the swap and drop claim-unsafe deletions

- The startup swap gated only on the env opt-out, so a payload staged
  automatically still installed after the user disabled automatic
  updates via [upgrade] auto_install = false. The swap now loads the
  persisted preference (only when an automatic stage is actually
  pending) and skips it, exactly like the env opt-out; manual stages
  still always apply.
- Superseding a staged version deleted its exe through an uncoordinated
  read-then-remove that could pull the payload from a live swap. The
  supersede now removes only the old metadata record — the metadata
  write atomically replaces it, and an unreferenced exe is reaped by a
  later orphan cleanup. removeStagedNativeUpdate, left with no callers,
  is removed.
- docs: the kimi upgrade reference (en + zh) no longer claims Windows
  native installations cannot upgrade automatically; native installs
  download and verify in the foreground and swap on the next start.

* fix: gate on claimed metadata, stop shared-path deletes on failure, exact smoke match

- The opt-out gate evaluated a pre-claim snapshot of the staged
  metadata, but the claim could pick up a different (automatic) stage a
  downloader published in between — smuggling it past the gate. The
  env/preference check now runs on the CLAIMED metadata; when disabled,
  the claim is restored via create-if-absent link so a newer stage is
  never overwritten and a later launch can still apply it. The checksum
  re-verify moves after the gates so opted-out launches stop paying for
  the hash.
- The download-failure cleanup still deleted the shared staged-exe path
  based on snapshot reference checks — the same publication race as the
  paths already fixed. It now removes only the attempt's privately owned
  .part file; the shared exe is left for the age-gated orphan cleanup.
- The smoke check accepted the staged version as a substring of the
  --version output, so a mispublished 1.2.30 binary would satisfy a
  1.2.3 target with a matching manifest checksum. It now requires the
  trimmed output to equal the staged version exactly.

* fix: confirm the manual marker before reporting stage adoption

promoteStagedUpdateToManual silently no-oped when a startup swap had
claimed the state file, while the adoption paths still reported success
with manual: true synthesized — under the env opt-out the restored
automatic metadata would then be skipped on every later launch despite
the upgrade's success message. The helper now verifies the marker with a
confirming read (one retry) and returns whether it persisted; the
already-staged branch falls through to a fresh stage when it does not,
and the same-version wait loop only adopts after a confirmed promotion.

* fix(cli): verify the staged payload digest before adopting it as already-staged

readStagedNativeUpdate checks only the recorded size, so a same-size
corruption after the download was adopted and reported as success, only
for the startup swap's claim-time re-verify to reject and discard it.
Compare the actual sha256 before returning already-staged; a mismatch
falls through and re-stages from the CDN.

* fix(cli): keep staged metadata until its replacement is ready

Two related races around staged.json, both reported against the
duplicate-downloader residual:

- stageNativeUpdate deleted the previous record before downloading its
  replacement; a pathname-only delete can remove a concurrent worker's
  freshly published record, orphaning a payload whose worker already
  reported success. The old record now stays until the final atomic
  metadata write replaces it.
- promoteStagedUpdateToManual wrote the marker unconditionally onto
  whichever generation owned staged.json. It now takes the adopted record
  and promotes only while the on-disk metadata still matches it, and the
  post-write confirmation requires the promoted candidate itself.

* fix(cli): preserve the exe referenced by the current staged record during orphan cleanup

Since the supersede path now keeps the previous staged.json until the
final atomic write replaces it, an aged staged exe is still the
applicable update while its replacement downloads — but
cleanupStagingOrphans only pinned exes referenced by swap claim files,
so a payload older than the grace period was unlinked out from under
its own record. Read staged.json itself in the pinning pass so the
current record's exe is preserved like any live claim's.

* chore(kimi-code): reword the native auto-update changeset

* chore(kimi-code): trim the native auto-update changeset

* fix(cli): support update locking on filesystems without hard links

link() fails with ENOTSUP/ENOSYS/EPERM on FAT/exFAT and some network
mounts, which aborted every native update before the download. Add a
shared createFileIfAbsent primitive (hard-link a fully written temp
file, falling back to an exclusive create + write) and use it for the
install lock, its takeover marker, and the swap's claim restore. The
fallback's create->write gap is observable, so the lock inspection now
grants young unparseable content a publish grace before sweeping it as
crash residue.

* fix(cli): publish staged exes under unique names and recover orphaned claims

Two related robustness fixes in the staged swap flow:

- A staged executable is now published under a unique per-worker name
  (kimi-<version>.<pid>.<epoch-ms>.<n>[.exe]) and never replaced; the
  atomic metadata write retargets the pointer. The pathname a swap
  validates at claim time can no longer be exchanged by a concurrent
  same-version publisher between validation and install.
- restoreClaimedUpdate only drops the claim when the restore landed or a
  newer stage holds the state-file path; transient failures retain it.
  The stale-claim sweep now restores aged claims (create-if-absent)
  instead of deleting them, so a stage orphaned by a dead swap or a
  transient restore failure is retried on a later launch.

* fix(cli): verify the staged payload digest in the lock-wait adoption path

waitForStagedUpdate relied on readStagedNativeUpdate, which checks only
the recorded size: while a holder re-stages a same-size-corrupted
payload (its metadata is replaced only when the repaired generation
publishes), a waiter could promote and report the corrupt stage as
downloaded, and startup would later reject its checksum. Apply the same
integrity bar as stageNativeUpdate's already-staged path — adopt only a
payload that hashes to its recorded checksum; a mismatch falls through
to the lock poll, which takes over once the holder finishes without
repairing it.

* fix(cli): serialize swap critical sections and preserve in-flight publishes

- The fresh-claim sweep is only a directory snapshot: two processes could
  both pass it before either claimed, then rename the same installed exe
  concurrently and delete each other's rollback backup. A create-if-absent
  swap mutex (swap.lock, age-gated like the takeover marker) now serializes
  the executable-renaming section; the loser restores its claim and defers.
  The mutex is released as soon as the new exe is in place, before the
  re-exec, so it is never held for the child session's lifetime.
- claimStagedUpdate no longer destroys a claimed record that is unparseable
  but was young at claim time: on filesystems without hard links the
  exclusive-create publish is observable mid-write, and discarding it would
  orphan the staged exe while the writer reports success. Such a record is
  put back with the same inode so the writer completes it; aged corrupt
  residue and well-formed records with a missing/changed exe are still
  discarded.

* fix(cli): keep backup cleanup inside the swap mutex

The early release let a subsequent swap rename the just-installed exe to
the shared .bak path while the previous swap's cleanup was still about to
unlink that same path, destroying the second swap's rollback source. The
mutex now covers the backup cleanup; the cosmetic staging-dir rmdir and
the re-exec stay outside it.
2026-08-18 17:17:18 +08:00

18 KiB
Raw Permalink Blame History

kimi 命令

kimi 是 Kimi Code CLI 的主命令,用于在终端中启动一次交互式会话。不带任何参数运行时,它会在当前工作目录下开启一个新会话;配合不同的 flag可以续上历史会话、跳过审批、从 Plan 模式开始,或者指定自定义的 Skills 目录。

kimi [options]
kimi <subcommand> [options]

主命令选项

所有 flag 都是可选的,直接运行 kimi 即可进入交互式会话:

选项 简写 说明
--version -V 打印版本号并退出
--help -h 显示帮助信息并退出
--session [id] -S 恢复一个会话。带 ID 时直接打开指定会话;不带 ID 时进入交互式选择器
--continue -c 继续当前工作目录下最近一次的会话,无需手动指定 ID
--model <model> -m 为本次启动指定模型别名。省略时新会话使用配置文件中的 default_model
--prompt <prompt> -p 非交互执行单次 prompt并把 Assistant 输出流式写到 stdout。该模式不会打开 TUI
--output-format <format> 设置非交互输出格式,支持 textstream-json。仅可与 --prompt 一起使用,默认 text
--yolo -y 自动批准普通工具调用,跳过审批请求
--auto 以 auto 权限模式启动工具审批自动处理Agent 不会向用户提问
--plan 以 Plan 模式启动新会话AI 会优先使用只读工具进行探索和规划
--skills-dir <dir> 从指定目录加载 Skills替换自动发现的用户和项目目录。可重复传入
--agent <name> 以指定 Agent 作为 main agent 启动新会话。不能与 --session/--continue 同时使用
--agent-file <path> 从 Markdown 文件加载自定义 Agent 并为新会话选中它。不可重复传入,也不能与 --agent--session--continue 同时使用
--add-dir <dir> 为本次会话添加额外的工作目录。相对路径按当前工作目录解析。可重复传入

-r / --resume--session 的隐藏别名;--yes--auto-approve--yolo 的隐藏别名,在帮助信息中不显示。

::: warning 注意 --yolo 会跳过普通工具调用的人工确认,包括文件写入和 Shell 命令执行请只在受信任的工作目录下使用。Plan 模式的退出审批不会被 --yolo 跳过Plan 模式下的 Bash 按普通放行规则处理。 :::

flag 冲突规则

以下组合会在启动时被拒绝:

  • --continue--session 互斥——两者都表示"恢复历史会话"
  • --yolo--auto 互斥——两种权限模式互斥
  • --prompt 不能与 --yolo--auto--plan 同时使用——非交互模式固定使用 auto 权限
  • --output-format 只能与 --prompt 一起使用

恢复会话时,可以通过 --auto--yolo--plan 覆盖原会话保存的权限或计划模式。例如,kimi --continue --auto 会恢复最近会话并切换到 auto 权限模式。

典型用法

直接运行开启新会话:

kimi

从上次中断的地方继续(自动找到当前目录最近的会话):

kimi --continue

从历史会话列表中挑选,或直接指定已知 ID

kimi --session
kimi --session 01HZ...XYZ

跳过审批确认,适合已知安全的批处理任务:

kimi --yolo

让 Agent 自行处理一切,不再向用户提问:

kimi --auto

先阅读代码、产出实现计划,而不是立刻动手修改文件:

kimi --plan

自定义 Skills 目录

有两种方式指定 Skills 目录,语义不同:

  • --skills-dir <dir>CLI flag替换自动发现的用户和项目目录,仅对本次启动生效。可重复传入以叠加多个目录:

    kimi --skills-dir /path/to/team-skills --skills-dir ./local-skills
    
  • extra_skill_dirsconfig.toml叠加到自动发现的目录之上,长期生效,适合配置团队共享 Skills。详见 Agent Skills

自定义 Agent

--agent--agent-file 用于选择驱动新会话的 Agent在 print 模式(kimi -p)和交互式 TUI 中均可使用:

kimi --agent reviewer
kimi -p --agent reviewer "审查这个分支上的改动"

--agent-file 以最高优先级注册单个 Agent 文件(仅本次启动)并选中它;该 flag 不可重复传入,--agent--agent-file 互斥。两个 flag 都仅在新建会话时有效——都不能与 --session/--continue 组合,因为 Agent 在会话创建时绑定,恢复会话时会自动还原已绑定的 Agent。选择在会话首次绑定后即固定之后不可切换在 TUI 中,这些 flag 只绑定启动时的会话,之后在同一进程内新建的会话(例如通过 /new)使用默认 Agent。Agent 文件格式与发现目录详见 Agent 与 subagent

非交互执行

在脚本或 CI 中运行单次 prompt 时,使用 -p

kimi -p "Summarize the current repository status"

输出采用 transcript 样式thinking 内容和 Assistant 正文都以 开头换行后两个空格缩进。Assistant 正文输出到 stdoutthinking、工具进度和"恢复会话"提示输出到 stderr。-p 模式不会请求人工审批,普通工具调用按 auto 权限策略处理,静态 deny 规则仍然生效。

临时切换模型:

kimi -m kimi-code/kimi-for-coding -p "Explain the latest diff"

需要结构化读取输出时,使用 stream-json 格式——stdout 每行都是一个 JSON 对象:

kimi -p "List changed files" --output-format stream-json

stream-json 模式下,普通回复输出 Assistant 消息;模型调用工具时,先输出带 tool_calls 的 Assistant 消息,再输出对应的 Tool 消息,最后继续输出后续 Assistant 消息。thinking 内容不会写入 JSONL工具进度和恢复会话提示仍写到 stderr。

子命令

kimi 提供以下子命令:login(非交互式登录)、acpACP IDE 模式)、web(前台运行本地 REST/WebSocket/web 服务并打开 web UIdoctor(校验配置文件)、export(导出会话)、migrate(迁移旧版数据)、upgrade(检查更新)、provider(管理供应商)。

kimi login

通过 RFC 8628 device-code 流程登录 Kimi Code OAuth无需进入 TUI。命令会发起一次 device authorization 请求,将验证地址和用户码打印到 stderr然后轮询直到浏览器侧完成授权。生成的 token 写入与 TUI /login 相同的本地位置,下次启动 kimi 时会自动加载。

kimi login

该子命令没有任何 flag。在轮询期间随时按 Ctrl-C 可取消登录;取消或失败时退出码为 1,成功为 0

kimi acp

把 Kimi Code CLI 切换到 ACPAgent Client Protocol模式在标准输入/输出上以 JSON-RPC 形式与 IDE 对话,让编辑器直接驱动 kimi 的会话和工具调用。通常不需要手动运行——IDE 会把它作为子进程入口启动。配置方式见在 IDE 中使用,技术细节见 kimi acp 参考

kimi acp

kimi web

在当前终端前台运行本地 Kimi 服务 —— 同一个进程同时挂载 REST + WebSocket API 与 web UI —— 并在服务就绪后用默认浏览器打开 web UI。命令会一直挂在终端直到收到 SIGINT / SIGTERM(如 Ctrl-C)时干净退出。

服务运行时,GET /openapi.json 会返回 REST OpenAPI 文档,GET /asyncapi.json 会返回本地 WebSocket 协议的 AsyncAPI 文档。用 API 驱动会话的完整流程见本地服务与 API,协议细节见服务 API

kimi web                 # 前台运行服务并打开浏览器
kimi web --no-open       # 不打开浏览器
kimi web --port 58628    # 指定绑定端口

同一 home 目录下可以同时运行多个实例:每个实例注册到 ~/.kimi-code/server/instances/,端口被占用时自动 +1 重试58628、58629……

选项 说明
--port <port> 绑定端口;默认 58627;被占用时自动 +1 重试
--host [host] 绑定地址;缺省 127.0.0.1(仅本机),裸 --host0.0.0.0(所有网卡)
--allowed-host <host...> DNS 重绑定检查额外允许的 Host 头,可重复或逗号分隔
--log-level <level> 按所选级别开启服务日志;默认不输出
--debug-endpoints 挂载 /api/v1/debug/* 调试路由(默认关闭)
--dangerous-bypass-auth 关闭所有 REST 与 WebSocket 路由的 bearer token 鉴权,使 web UI 无需 token 即可连接;仅用于可信网络或自有鉴权代理之后
--no-open 就绪后不自动打开浏览器

kimi web 默认只绑定本机 loopback 地址,并在启动横幅中打印 bearer tokenweb UI 通过 URL 的 #token= 片段自动完成鉴权。

::: info 提示 kimi server 命令树已废弃:任何 kimi server … 调用(含全部旧子命令)只会打印弃用提示并以退出码 1 结束,请改用 kimi web。唯一的例外是 kimi server kill,它仍然可用,仅用于停止 0.28.0 之前版本启动的服务。该提示将在 Kimi Code 下个大版本移除。 :::

::: danger 警告 --dangerous-bypass-auth 会彻底关闭鉴权。任何能访问该端口的人都能完全控制你的会话、文件系统和 shell。请仅在可信网络或自有鉴权反向代理之后使用用完后按 Ctrl+C 停止服务。 :::

kimi server kill

已废弃——仅用于停止 0.28.0 之前的 Kimi Code 版本启动的服务。那些版本可能在后台遗留服务进程,记录在 legacy 单实例锁文件 ~/.kimi-code/server/lock 中;该命令先请求 POST /api/v1/shutdown 优雅退出,再对锁中记录的 pid 发 SIGTERM、必要时升级为 SIGKILL并在确认进程退出后删除锁文件。kimi web 启动的服务在前台运行,直接用 Ctrl+C 停止即可。

kimi web rotate-token

生成新的持久化 bearer token写入 ~/.kimi-code/server.token),旧 token 立即失效。token 是整个 home 目录共享的,所有运行中的实例会在下一次鉴权校验时自动换用新 token无需重启。

kimi doctor

校验 config.tomltui.toml,不会启动 TUI也不会修改任一文件。默认检查 KIMI_CODE_HOME 下的文件;未设置该环境变量时检查 ~/.kimi-code。默认路径缺失时会显示为跳过,因为内置默认值仍可生效。

kimi doctor
命令 说明
kimi doctor 校验默认 config.tomltui.toml
kimi doctor config [path] 只校验 config.toml;传入 path 时使用该文件而不是默认文件
kimi doctor tui [path] 只校验 tui.toml;传入 path 时使用该文件而不是默认文件

显式传入路径时,文件必须存在。所有被检查的文件都有效或被跳过时,退出码为 0;任何指定文件缺失或配置无效时,退出码为 1

# 检查默认配置文件
kimi doctor

# 只检查默认运行时配置
kimi doctor config

# 替换正式 TUI 配置前,先检查候选文件
kimi doctor tui ./tui.toml

kimi export

把一个会话打包成 ZIP 文件,便于分享、归档或提交问题反馈。

kimi export [sessionId] [options]
参数 / 选项 简写 说明
sessionId 要导出的会话 ID。省略时自动选择当前工作目录下最近一次的会话并要求确认
--output <path> -o 输出 ZIP 文件路径。省略时写入当前目录下的默认文件名
--yes -y 跳过默认会话的确认提示,直接导出
--no-include-global-log 不打包全局诊断日志。默认包含

导出包含目标会话目录内的所有文件。全局诊断日志(~/.kimi-code/logs/kimi-code.log)默认包含,因为它可能含有其他会话或项目的事件;不想分享时加 --no-include-global-log

# 导出当前工作目录最近一次会话,跳过确认
kimi export -y

# 导出指定会话到自定义路径
kimi export 01HZ...XYZ -o ./bug-report.zip

# 排除全局诊断日志
kimi export 01HZ...XYZ -o ./bug-report.zip --no-include-global-log

kimi migrate

将旧版 kimi-cli 的本地数据迁移到 kimi-code包括历史会话和配置文件。纯交互式运行会引导你完成全流程。

kimi migrate

完整迁移说明见从 kimi-cli 迁移

kimi upgrade

立即检查最新版本并展示更新提示,选择操作后退出。也可以使用别名 kimi update

kimi upgrade

对全局 npm、pnpm、yarn、bun 安装,kimi upgrade 会展示更新选项;选择 Install update now 后运行对应的前台安装命令。对 native 安装(含 Windows会在前台下载并校验新二进制并在下次启动时替换生效。当前安装方式无法自动升级时改为打印手动更新命令。

kimi vis

在浏览器中启动会话可视化工具,直观查看一次会话的全过程。命令会启动一个指向本地会话的进程内服务器,打印访问地址并打开浏览器,持续运行直到你按下 Ctrl-C

kimi vis [sessionId] [options]
参数 / 选项 说明
sessionId 直接打开指定会话的可视化页面。省略时打开列出所有会话的首页
--port <number> 绑定的端口。默认自动挑选一个空闲端口
--host <host> 绑定的主机。默认 127.0.0.1
--no-open 不自动打开浏览器,仅打印访问地址
# 启动可视化工具并在浏览器中打开首页
kimi vis

# 直接打开指定会话
kimi vis 01HZ...XYZ

# 绑定固定主机和端口且不打开浏览器(例如在远程主机上)
kimi vis --host 0.0.0.0 --port 8123 --no-open

kimi provider

在 shell 中管理供应商,相当于 TUI 中 /provider 的非交互版本。适合脚本化部署、CI 初始化,以及在新机器上一行完成配置。

kimi provider <action> [options]

包含五个动作:

kimi provider add <url>

从自定义 registryapi.json)批量导入所有供应商。命令会拉取 registry为每个条目创建 [providers.<id>][models.<alias>],并写入 source 元数据,使 TUI 下次启动时自动刷新同一 registry 地址下的供应商和模型。

参数 / 选项 说明
<url> Registry 地址
--api-key <key> 访问 registry 时携带的 Bearer token。未传时回退到环境变量 KIMI_REGISTRY_API_KEY,必填
kimi provider add https://registry.example.com/v1/models/api.json --api-key YOUR_KEY

# 或通过环境变量(适合 CI / .envrc
KIMI_REGISTRY_API_KEY=YOUR_KEY kimi provider add https://registry.example.com/v1/models/api.json

如果某个 provider id 已存在,会先删除再重新写入。不会自动设置默认模型,后续可用 -m 或 TUI 内的 /model 选择。

kimi provider remove <providerId>

删除指定供应商及其所有模型 alias。如果被删除的供应商正好是 default_model 所属,则同时清空 default_model

kimi provider remove kohub

kimi provider list

按行打印每个已配置的供应商,含类型、模型数量、来源。加 --json 可输出原始的 providersmodels 表,便于程序化处理。

kimi provider list
kimi provider list --json | jq '.providers | keys'

kimi provider catalog list [providerId]

在不修改任何配置的情况下浏览公开的 models.dev 模型目录。不传参数时列出所有供应商及协议类型和模型数量;传 providerId 时列出该供应商下所有模型的上下文窗口和能力。目录地址不可达时会使用内置目录快照。

参数 / 选项 说明
[providerId] 可选,要查看的供应商 id
--filter <substring> 按 id 或 name 大小写不敏感子串过滤
--url <url> 覆盖 catalog 地址,默认 https://models.dev/api.json
--json 以 JSON 形式输出匹配片段
kimi provider catalog list
kimi provider catalog list --filter anthropic
kimi provider catalog list anthropic

kimi provider catalog add <providerId>

按 id 从 catalog 直接导入一个已知供应商协议类型、base URL、模型信息均由 catalog 提供,只需提供 API key。catalog 未声明协议的供应商(如 xai、openrouter 这类厂商专用 SDK按 OpenAI 兼容协议导入,并在输出中标注 "guessed"catalog 未提供可用端点时需用 --base-url 显式指定。专有协议(如 Amazon Bedrock无法导入。公共目录不可达时会回退到内置目录快照离线或网络受限环境下也能导入。

参数 / 选项 说明
<providerId> catalog 中的供应商 idanthropicopenai
--api-key <key> 供应商 API key。未传时回退到 KIMI_REGISTRY_API_KEY,必填
--default-model <modelId> 可选,导入后把 default_model 设为 <providerId>/<modelId>
--base-url <url> 覆盖 catalog 声明的端点catalog 未提供端点(或仅有环境变量占位符)时必填
--url <url> 覆盖 catalog 地址,默认 https://models.dev/api.json
kimi provider catalog list anthropic          # 先看可选的模型
kimi provider catalog add anthropic --api-key sk-ant-... --default-model claude-opus-4-7

下一步

  • 斜杠命令 — 交互式 TUI 内的控制命令速查
  • 配置文件default_model、权限模式等启动参数的持久化配置
  • Agent Skills--skills-dir 加载的 Skill 文件格式
  • Agent 与 subagent — 内置 subagent、自定义 Agent 文件与通过 --agent 选择 main agent