Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/apps/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ only when the current invocation may approve tool requests. Non-interactive `exe
`AskUserQuestion`; provide all required input in the initial prompt. The hidden legacy `--confirm`
flag maps to the safe default and should not be used in new automation.

The interactive TUI supports per-session worktree isolation through `/worktree`. Run the command
without arguments to toggle it, or use `/worktree on`, `/worktree off`, and `/worktree status`.
The header shows the active branch and `Worktree: on|off`; detached managed worktrees use their base
commit as the branch label. The existing session lifecycle owner creates, persists, restores, and
releases the managed worktree. Isolation can only be changed before the session's first message, and
a released worktree with local or unpublished work is retained with its path reported in the chat.
This command is TUI-only and does not change the non-interactive `exec` contract.

### Structured output

| Format | stdout contract |
Expand Down
26 changes: 26 additions & 0 deletions src/apps/cli/src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ pub(crate) enum ActionHandler {
History,
Usage,
ToggleAutoApprove,
ToggleWorktree,
Exit,
Login,
Logout,
Expand Down Expand Up @@ -546,6 +547,21 @@ static ACTION_SPECS: &[ActionSpec] = &[
shortcut_label: None,
slash_on_startup: false,
},
ActionSpec {
id: "toggle_worktree",
name: "Worktree",
aliases: &["/worktree"],
description: "Toggle worktree isolation for the current session",
contexts: CHAT,
availability: ActionAvailability::Idle,
handler: ActionHandler::ToggleWorktree,
default_bindings: &[],
fallback_bindings: &[],
shortcut_field: None,
palette: palette("Session", false),
shortcut_label: None,
slash_on_startup: false,
},
ActionSpec {
id: "exit",
name: "Exit the app",
Expand Down Expand Up @@ -1876,6 +1892,16 @@ mod tests {
assert!(!action.available(ActionState::chat(true, false)));
}

#[test]
fn worktree_is_chat_only_and_idle_only() {
assert!(action_for_alias("/worktree", ActionContext::Startup).is_none());

let action = action_for_alias("/worktree", ActionContext::Chat).unwrap();
assert_eq!(action.handler, ActionHandler::ToggleWorktree);
assert!(action.available(ActionState::chat(false, false)));
assert!(!action.available(ActionState::chat(true, false)));
}

#[test]
fn extension_management_uses_capability_entries_instead_of_external_commands() {
let tools = action_for_alias("/tools", ActionContext::Chat).unwrap();
Expand Down
Loading