Skip to content

feat(cli): add git worktree support for isolated sessions#2073

Open
cal-gooo wants to merge 1 commit intoMoonshotAI:mainfrom
cal-gooo:feat/worktree-support
Open

feat(cli): add git worktree support for isolated sessions#2073
cal-gooo wants to merge 1 commit intoMoonshotAI:mainfrom
cal-gooo:feat/worktree-support

Conversation

@cal-gooo
Copy link
Copy Markdown

@cal-gooo cal-gooo commented Apr 25, 2026

Summary

Add --worktree / -W flag to create a new git worktree and run the session inside it. This allows multiple parallel kimi sessions on the same repository without file conflicts or branch-switching overhead.

New CLI Options

  • --worktree, -W — Create a new git worktree for the session
  • --worktree-name <name> — Custom worktree directory name
  • --worktree-branch <branch> — Branch to check out (default: detached HEAD)

Usage Example

cd ~/my-project
kimi --worktree -p "refactor the auth module"

# With a custom name and branch
kimi --worktree --worktree-name feature-oauth --worktree-branch feature/oauth -p "implement OAuth2"

Implementation Details

  • New worktree.py module with create_worktree(), remove_worktree(), list_worktrees(), and find_git_root() helpers.
  • SessionState extended with worktree_path and parent_repo_path.
  • Session.delete() cleans up the git worktree to avoid accumulation of abandoned worktrees.
  • Conflict checks prevent combining --worktree with --continue or --session.

Tests

  • Unit tests for worktree creation, removal, listing, and error cases.
  • CLI tests for option parsing and conflict detection.
  • All 1825 tests pass.

Motivation

Inspired by Codex and Claude Code worktree workflows, which use git worktrees to isolate parallel agent sessions on the same repo.


Open in Devin Review

devin-ai-integration[bot]

This comment was marked as resolved.

@cal-gooo cal-gooo force-pushed the feat/worktree-support branch from 4facdcb to 091d7b1 Compare April 25, 2026 14:45
devin-ai-integration[bot]

This comment was marked as resolved.

Add --worktree / -W flag to create a new git worktree and run the
session inside it. This allows multiple parallel kimi sessions on the
same repository without file conflicts or branch-switching overhead.

New CLI options:
  --worktree, -W          Create a new git worktree for the session
  --worktree-name TEXT    Custom worktree directory name
  --worktree-branch TEXT  Branch to check out (default: detached HEAD)

Changes:
- New worktree.py module with create_worktree(), remove_worktree(),
  list_worktrees(), and find_git_root() helpers.
- SessionState extended with worktree_path and parent_repo_path.
- Session.delete() cleans up the git worktree to avoid accumulation.
- Conflict checks prevent combining --worktree with --continue or
  --session (resuming in a worktree doesn't make sense).

PR review fixes:
- Add --detach flag when creating worktree without a branch, preventing
  git from auto-creating a branch named after the worktree directory.
- Fix _rmtree_sync fallback to convert KaosPath to pathlib.Path,
  avoiding silent failures from shutil.rmtree type errors.
- Guard worktree creation with _worktree_created flag so Reload
  re-entries (e.g. /model, /theme) do not create nested worktrees.

Tests:
- Unit tests for worktree creation, removal, listing, and error cases.
- CLI tests for option parsing and conflict detection.

Inspired by Codex and Claude Code worktree workflows.
@cal-gooo
Copy link
Copy Markdown
Author

Forwarding two findings from automated reviewers on the stacked PR #2076. Both apply to code originating in this PR:

1. Session.delete(remove_worktree=True) can reap a worktree shared by other sessions (Codex P1)

File: src/kimi_cli/cli/__init__.py:770_delete_empty_session(session, *, remove_worktree: bool = True)

--worktree flows allow multiple sessions in the same worktree (e.g. via /new). When the latest session ends empty, _post_run calls _delete_empty_session(last_session) with the default remove_worktree=True, which removes the worktree even if earlier sessions still reference it — leaving those older sessions pointing at a deleted working directory and losing any uncommitted work.

Suggested fix: flip the default to False for implicit cleanup paths, or check list_worktrees / count sessions owning the same worktree_path before allowing removal. The explicit caller at line 823 (_delete_empty_session(old, remove_worktree=False)) already does the safe thing; the default for the other two call sites (lines 792, 861) should match.

2. remove_worktree parameter shadowed by same-name import (Devin 🟡)

File: src/kimi_cli/session.py:109 — inside Session.delete(self, *, remove_worktree: bool = True):

if remove_worktree and self.state.worktree_path and self.state.parent_repo_path:
    from kimi_cli.worktree import remove_worktree   # ← rebinds local name
    ...
    await remove_worktree(...)

Python has no block scoping, so after the import the local remove_worktree is the function for the rest of the method (the boolean is checked before the import, so the current code happens to work). Any future addition that checks the boolean after the import would silently see a truthy function object.

Suggested fix: alias the import.

-            from kimi_cli.worktree import remove_worktree
+            from kimi_cli.worktree import remove_worktree as _remove_worktree
             ...
-                await remove_worktree(
+                await _remove_worktree(
                     KaosPath(self.state.parent_repo_path),
                     KaosPath(self.state.worktree_path),
                 )

Both findings were originally filed on #2076 by Codex and Devin automated reviewers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant