-
Notifications
You must be signed in to change notification settings - Fork 397
feat(kimi-code): add -w, --worktree [name] flag for isolated sessions #818
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 7 commits
b7db693
3974aa3
c61f5d5
3bbf152
a74eb19
91be1d7
6a86ada
ab83d9f
4710074
42902f6
950156e
b8a2539
751c395
389a09b
dfd32f2
d24988a
a80cdc2
b1e69b4
3c0958f
5f4ea9f
35f9612
8e4c290
0379c3a
3cea709
e60c17f
44b1296
49fa0b2
2a6e0aa
f04656d
043de86
9cd5098
180c924
b2a5dd9
7c4b24d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| --- | ||
| "@moonshot-ai/agent-core": minor | ||
| "@moonshot-ai/kimi-code": minor | ||
| --- | ||
|
|
||
| Add `-w, --worktree [name]` flag to create a new git worktree for the session, and surface the worktree metadata in the agent system prompt. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,8 @@ import type { CLIOptions } from './cli/options'; | |
| import { OptionConflictError, validateOptions } from './cli/options'; | ||
| import { runPrompt } from './cli/run-prompt'; | ||
| import { runShell } from './cli/run-shell'; | ||
| import { relative, resolve } from 'node:path'; | ||
| import { createWorktree, findGitRoot, removeWorktree, WorktreeError } from './utils/git/worktree'; | ||
| import { formatStartupError } from './cli/startup-error'; | ||
| import { runPluginNodeEntry } from './cli/sub/plugin-run-node'; | ||
| import { handleUpgrade } from './cli/sub/upgrade'; | ||
|
|
@@ -38,6 +40,22 @@ import { cleanupStaleNativeCacheForCurrent } from './native/native-assets'; | |
| import { installNativeModuleHook } from './native/module-hook'; | ||
| import { runNativeAssetSmokeIfRequested } from './native/smoke'; | ||
|
|
||
| function prepareWorktree(worktreeName: string): { worktreePath: string; parentRepoPath: string } { | ||
| const cwd = process.cwd(); | ||
| const repoRoot = findGitRoot(cwd); | ||
| if (repoRoot === null) { | ||
| throw new WorktreeError('--worktree requires the working directory to be inside a git repository.'); | ||
| } | ||
| const worktreePath = createWorktree(repoRoot, worktreeName || undefined); | ||
| const relativeCwd = relative(repoRoot, cwd); | ||
| const targetCwd = | ||
| relativeCwd.length > 0 && relativeCwd !== '.' | ||
| ? resolve(worktreePath, relativeCwd) | ||
| : worktreePath; | ||
| process.chdir(targetCwd); | ||
|
rrva marked this conversation as resolved.
Outdated
|
||
| return { worktreePath, parentRepoPath: repoRoot }; | ||
| } | ||
|
|
||
| export async function handleMainCommand(opts: CLIOptions, version: string): Promise<void> { | ||
| let validated: ReturnType<typeof validateOptions>; | ||
| try { | ||
|
|
@@ -58,12 +76,46 @@ export async function handleMainCommand(opts: CLIOptions, version: string): Prom | |
| process.exit(0); | ||
| } | ||
|
|
||
| if (validated.uiMode === 'print') { | ||
| await runPrompt(validated.options, version); | ||
| return; | ||
| if (opts.worktree !== undefined) { | ||
| try { | ||
| const { worktreePath, parentRepoPath } = await prepareWorktree(opts.worktree); | ||
|
rrva marked this conversation as resolved.
Outdated
|
||
| opts.worktreePath = worktreePath; | ||
| opts.parentRepoPath = parentRepoPath; | ||
| } catch (error) { | ||
| if (error instanceof WorktreeError) { | ||
| process.stderr.write(`error: ${error.message}\n`); | ||
| process.exit(1); | ||
| } | ||
| throw error; | ||
| } | ||
| } | ||
|
|
||
| await runShell(validated.options, version); | ||
| try { | ||
| if (validated.uiMode === 'print') { | ||
| await runPrompt(validated.options, version); | ||
| return; | ||
| } | ||
|
|
||
| await runShell(validated.options, version); | ||
| } catch (error) { | ||
| // If the shell runner failed during startup after we created a worktree, | ||
| // the worktree is still empty (no session ran), so clean it up to avoid | ||
| // leaks. Print mode intentionally leaves the worktree inspectable even on | ||
| // failure, so we do not clean it up here. | ||
| if ( | ||
| validated.uiMode !== 'print' && | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When Useful? React with 👍 / 👎. |
||
| opts.worktreePath !== undefined && | ||
| opts.parentRepoPath !== undefined | ||
| ) { | ||
| try { | ||
| removeWorktree(opts.parentRepoPath, opts.worktreePath); | ||
| } catch (cleanupError) { | ||
| // Best-effort cleanup only; do not let cleanup failures mask the original error. | ||
| log.warn('Failed to clean up git worktree after runner startup failed', cleanupError); | ||
| } | ||
| } | ||
| throw error; | ||
| } | ||
| } | ||
|
|
||
| /** `kimi migrate`: launch the migration screen only, then exit. */ | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.