MoonshotAI / MoonshotAI/kimi-code
installer: the kimi.bak rollback backup is deleted by the next CLI launch
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 1.2k
- Avg merge
- 11h 53m
- Merged PRs (30d)
- 350
Description
Summary
The native installer backs up the existing binary as <install_dir>/bin/kimi.bak and tells the user it did so — but the next kimi launch deletes exactly that file. The rollback point the installer just advertised does not survive one run of the CLI.
Why
install.sh (https://code.kimi.com/kimi-code/install.sh):
if [ -f "${KIMI_INSTALL_DIR}/bin/kimi" ]; then
cp "${KIMI_INSTALL_DIR}/bin/kimi" "${KIMI_INSTALL_DIR}/bin/kimi.bak"
_log "Backed up existing kimi to ${KIMI_INSTALL_DIR}/bin/kimi.bak"
fi
The CLI's self-update uses the same path as its own swap scratch (apps/kimi-code/src/cli/update/native-swap.ts:579: let bakPath = \${deps.exePath}.bak``), and its startup hygiene wipes every such file:
// native-swap.ts:341 — cleanupBackups()
if (!entry.startsWith(`${base}.`) || !entry.endsWith('.bak')) continue;
const middle = entry.slice(base.length + 1, -'.bak'.length);
if (middle !== '' && !/^\d+$/.test(middle)) continue; // '' (kimi.bak) and <digits> both pass
await unlink(full).catch(() => {});
called from the startup sweep with no keepPath:
// native-swap.ts:421 — sweepStaleNativeUpdateArtifacts()
await cleanupBackups(exePath);
The function's own comment calls the targets "leftover .bak siblings of the exe from earlier swaps/installs" — i.e. the installer-created file is treated as debris by design. Note the swap success path does keep its backup (cleanupBackups(deps.exePath, bakPath)), but the next startup's sweep has no keepPath, so that one is removed as well.
Repro (linux, native install)
curl -fsSL https://code.kimi.com/kimi-code/install.sh | bash # prints "Backed up existing kimi to …/bin/kimi.bak"
ls ~/.kimi-code/bin/ # kimi kimi.bak
kimi --version # any invocation, including this one
ls ~/.kimi-code/bin/ # kimi ← kimi.bak is gone
Name-matched, not a general wipe — with dummy files in the same directory:
before: kimi.bak kimi.20260101.bak other.bak
after `kimi --version`: other.bak ← only the two matching names are removed
Impact
A user who wants to go back to the previous version after an upgrade follows the installer's message, looks for kimi.bak, and finds nothing. The only reliable recovery is re-running the installer with an explicit version.
Possible fixes
- Have
install.shuse a name the CLI never claims (e.g.kimi.bak.<version>/<timestamp>), or - make the startup sweep keep the newest
<exe>.bakinstead of deleting every match (keepPathalready exists for the swap path), or - state in the installer output that this backup is transient.
cc @liruifengv (native-swap / update)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read install.sh alongside apps/kimi-code/src/cli/update/native-swap.ts, especially cleanupBackups(), sweepStaleNativeUpdateArtifacts(), and the swap backup path. Reproduce the install, launch kimi once, and inspect the install directory. Done means the installer-advertised rollback backup survives the next CLI launch without breaking native update cleanup.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- shell, typescript
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100