mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-07-23 16:20:57 -07:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 80ff4bd39c |
@@ -38,14 +38,6 @@ folder, a dialog will automatically appear, prompting you to make a choice:
|
||||
Your choice is saved in a central file (`~/.gemini/trustedFolders.json`), so you
|
||||
will only be asked once per folder.
|
||||
|
||||
### Headless mode and automation
|
||||
|
||||
When running in headless mode (using the `-p` or `--prompt` flag), the trust
|
||||
dialog is bypassed automatically to ensure that non-interactive workflows and
|
||||
automation scripts are not interrupted. In this mode, the CLI operates with
|
||||
restricted permissions as if the folder were untrusted, unless the folder has
|
||||
been previously trusted through an interactive session.
|
||||
|
||||
## Understanding folder contents: The discovery phase
|
||||
|
||||
Before you make a choice, the Gemini CLI performs a **discovery phase** to scan
|
||||
|
||||
@@ -138,7 +138,7 @@ like `jq`. To get pure JSON data from the model, combine the
|
||||
fi
|
||||
|
||||
# Extract data
|
||||
gemini -p "Return a raw JSON object with keys 'version' and 'deps' from @package.json" --output-format json | jq -r '.response' > data.json
|
||||
gemini --output-format json "Return a raw JSON object with keys 'version' and 'deps' from @package.json" | jq -r '.response' > data.json
|
||||
```
|
||||
|
||||
**Windows PowerShell (`generate_json.ps1`)**
|
||||
@@ -151,7 +151,7 @@ like `jq`. To get pure JSON data from the model, combine the
|
||||
}
|
||||
|
||||
# Extract data (requires jq installed, or you can use ConvertFrom-Json)
|
||||
$output = gemini -p "Return a raw JSON object with keys 'version' and 'deps' from @package.json" --output-format json | ConvertFrom-Json
|
||||
$output = gemini --output-format json "Return a raw JSON object with keys 'version' and 'deps' from @package.json" | ConvertFrom-Json
|
||||
$output.response | Out-File -FilePath data.json -Encoding utf8
|
||||
```
|
||||
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
# A2A Server
|
||||
|
||||
The A2A Server is a core component of the Gemini CLI that implements the
|
||||
Agent-to-Agent (A2A) protocol. It enables external clients, such as IDEs or
|
||||
other AI agents, to interact with the Gemini CLI agent through a standardized,
|
||||
streaming interface.
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
> [!NOTE]
|
||||
> This is an experimental feature currently under active development.
|
||||
|
||||
The A2A Server allows Gemini CLI to function as a backend service, providing
|
||||
capabilities like code generation, tool execution, and workspace analysis to
|
||||
client applications like Zed, VS Code, and Gemini Code Assist.
|
||||
|
||||
## Overview
|
||||
|
||||
The A2A Server implements the `development-tool` extension for the A2A protocol.
|
||||
This extension defines a communication contract for rich, interactive workflows,
|
||||
including:
|
||||
|
||||
- **Task-based streaming:** Real-time updates on the agent's thoughts and tool
|
||||
invocations.
|
||||
- **Permission requests:** Standardized mechanism for the agent to request user
|
||||
approval before executing potentially sensitive tools.
|
||||
- **Tool lifecycle management:** A structured state machine for tracking tool
|
||||
execution from creation to completion.
|
||||
- **Slash command execution:** Programmatic access to built-in Gemini CLI
|
||||
commands.
|
||||
|
||||
## Usage
|
||||
|
||||
The A2A Server can be started independently or as part of an integrated
|
||||
workflow.
|
||||
|
||||
### Starting the server
|
||||
|
||||
In a development environment, you can launch the A2A Server from the project
|
||||
root using npm:
|
||||
|
||||
```bash
|
||||
npm run start:a2a-server
|
||||
```
|
||||
|
||||
This command builds the necessary dependencies and starts the server on its
|
||||
default port. The server provides an SSE (Server-Sent Events) stream for
|
||||
real-time updates to connected A2A clients.
|
||||
|
||||
### Integration with IDEs
|
||||
|
||||
Many IDE integrations use the A2A Server to power their "Agent Mode" features.
|
||||
For example, the [VS Code companion](../ide-integration/index.md) communicates
|
||||
with the A2A Server to execute complex coding tasks within your workspace.
|
||||
|
||||
## Key features
|
||||
|
||||
### Development tool extension
|
||||
|
||||
The A2A Server uses a specialized set of schemas to enable rich client
|
||||
interactions:
|
||||
|
||||
- **Agent thoughts:** Streams the agent's internal reasoning as it works through
|
||||
a task.
|
||||
- **Tool calls:** Provides a detailed, stateless representation of tool
|
||||
execution, including `PENDING`, `EXECUTING`, and `SUCCEEDED` statuses.
|
||||
- **Confirmation requests:** Requests user permission for shell commands, file
|
||||
edits, or MCP tool usage via the client UI.
|
||||
|
||||
### Separation of concerns
|
||||
|
||||
The A2A architecture enforces a strict separation of concerns:
|
||||
|
||||
1. **A2A Protocol:** Standardizes the communication and task management between
|
||||
the client and the Gemini CLI agent.
|
||||
2. **MCP (Model Context Protocol):** Serves as the authoritative interface for
|
||||
accessing client-side capabilities, such as reading active buffers or
|
||||
accessing the local file system.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you encounter issues with the A2A Server:
|
||||
|
||||
- **Check logs:** Review the server output for errors during initialization or
|
||||
client connection.
|
||||
- **Verify A2A compliance:** Ensure that the client application is correctly
|
||||
implementing the A2A protocol and the `development-tool` extension.
|
||||
- **Network permissions:** Ensure that the server has the necessary permissions
|
||||
to listen on its configured port and communicate with MCP servers.
|
||||
|
||||
## Next steps
|
||||
|
||||
- Learn about [Remote subagents](./remote-agents.md) and A2A connectivity.
|
||||
- Explore the [IDE integration guide](../ide-integration/index.md).
|
||||
@@ -89,7 +89,7 @@ manually run through this checklist.
|
||||
- [ ] Vertex AI
|
||||
|
||||
- **Basic prompting:**
|
||||
- [ ] Run `gemini -p "Tell me a joke"` and verify a sensible response.
|
||||
- [ ] Run `gemini "Tell me a joke"` and verify a sensible response.
|
||||
- [ ] Run in interactive mode: `gemini`. Ask a follow-up question to test
|
||||
context.
|
||||
|
||||
|
||||
+2
-17
@@ -95,11 +95,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "A2A Server",
|
||||
"badge": "🔬",
|
||||
"slug": "docs/core/a2a-server"
|
||||
},
|
||||
{ "label": "Agent Skills", "slug": "docs/cli/skills" },
|
||||
{ "label": "Checkpointing", "slug": "docs/cli/checkpointing" },
|
||||
{ "label": "Headless mode", "slug": "docs/cli/headless" },
|
||||
@@ -163,18 +158,8 @@
|
||||
"items": [
|
||||
{ "label": "Custom commands", "slug": "docs/cli/custom-commands" },
|
||||
{
|
||||
"label": "Enterprise administration",
|
||||
"collapsed": true,
|
||||
"items": [
|
||||
{
|
||||
"label": "Enterprise configuration",
|
||||
"slug": "docs/cli/enterprise"
|
||||
},
|
||||
{
|
||||
"label": "Enterprise Admin Controls",
|
||||
"slug": "docs/admin/enterprise-controls"
|
||||
}
|
||||
]
|
||||
"label": "Enterprise configuration",
|
||||
"slug": "docs/cli/enterprise"
|
||||
},
|
||||
{
|
||||
"label": "Ignore files (.geminiignore)",
|
||||
|
||||
@@ -15,13 +15,9 @@ Lists the names of files and subdirectories directly within a specified path.
|
||||
- **Tool name:** `list_directory`
|
||||
- **Arguments:**
|
||||
- `dir_path` (string, required): Absolute or relative path to the directory.
|
||||
- `ignore` (array, optional): Glob patterns to exclude (e.g.,
|
||||
`["*.tmp", "build/"]`).
|
||||
- `ignore` (array, optional): Glob patterns to exclude.
|
||||
- `file_filtering_options` (object, optional): Configuration for `.gitignore`
|
||||
and `.geminiignore` compliance.
|
||||
- `respect_git_ignore` (boolean, optional): Whether to respect `.gitignore`.
|
||||
- `respect_gemini_ignore` (boolean, optional): Whether to respect
|
||||
`.geminiignore`.
|
||||
|
||||
### `read_file` (ReadFile)
|
||||
|
||||
@@ -31,22 +27,8 @@ and PDF.
|
||||
- **Tool name:** `read_file`
|
||||
- **Arguments:**
|
||||
- `file_path` (string, required): Path to the file.
|
||||
- `start_line` (number, optional): The 1-based line number to start reading
|
||||
from.
|
||||
- `end_line` (number, optional): The 1-based line number to end reading at
|
||||
(inclusive).
|
||||
|
||||
### `read_many_files` (ReadManyFiles)
|
||||
|
||||
Reads and concatenates content from multiple files or entire directories. This
|
||||
is the tool triggered by the `@` symbol in your prompt.
|
||||
|
||||
- **Tool name:** `read_many_files`
|
||||
- **Arguments:**
|
||||
- `paths` (array of strings, required): List of paths to files or directories.
|
||||
- `ignore` (array of strings, optional): Glob patterns to exclude.
|
||||
- `file_filtering_options` (object, optional): Configuration for `.gitignore`
|
||||
and `.geminiignore` compliance.
|
||||
- `offset` (number, optional): Start line for text files (0-based).
|
||||
- `limit` (number, optional): Maximum lines to read.
|
||||
|
||||
### `write_file` (WriteFile)
|
||||
|
||||
|
||||
@@ -534,6 +534,7 @@ export const mockAppState: AppState = {
|
||||
};
|
||||
|
||||
const mockUIActions: UIActions = {
|
||||
toggleAlternateBuffer: vi.fn(),
|
||||
handleThemeSelect: vi.fn(),
|
||||
closeThemeDialog: vi.fn(),
|
||||
handleThemeHighlight: vi.fn(),
|
||||
|
||||
@@ -68,8 +68,10 @@ import {
|
||||
writeToStdout,
|
||||
disableMouseEvents,
|
||||
enterAlternateScreen,
|
||||
exitAlternateScreen,
|
||||
enableMouseEvents,
|
||||
disableLineWrapping,
|
||||
enableLineWrapping,
|
||||
shouldEnterAlternateScreen,
|
||||
startupProfiler,
|
||||
SessionStartSource,
|
||||
@@ -213,7 +215,7 @@ export const AppContainer = (props: AppContainerProps) => {
|
||||
});
|
||||
|
||||
useMemoryMonitor(historyManager);
|
||||
const isAlternateBuffer = config.getUseAlternateBuffer();
|
||||
const [isAlternateBuffer, setIsAlternateBuffer] = useState(config.getUseAlternateBuffer());
|
||||
const [corgiMode, setCorgiMode] = useState(false);
|
||||
const [forceRerenderKey, setForceRerenderKey] = useState(0);
|
||||
const [debugMessage, setDebugMessage] = useState<string>('');
|
||||
@@ -1550,6 +1552,23 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
type: TransientMessageType;
|
||||
}>(WARNING_PROMPT_DURATION_MS);
|
||||
|
||||
const [shownBufferToggleHint, setShownBufferToggleHint] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (isAlternateBuffer) return;
|
||||
|
||||
const isLongHistory = historyManager.history.length > 15;
|
||||
const isComplexPrompt = buffer.text.length > 200 || buffer.text.includes('\n');
|
||||
|
||||
if ((isLongHistory || isComplexPrompt) && !shownBufferToggleHint) {
|
||||
showTransientMessage({
|
||||
text: 'Tip: Press Alt+T to toggle full-screen mode for better scrolling/editing',
|
||||
type: TransientMessageType.Hint
|
||||
});
|
||||
setShownBufferToggleHint(true);
|
||||
}
|
||||
}, [historyManager.history.length, buffer.text, isAlternateBuffer, shownBufferToggleHint, showTransientMessage]);
|
||||
|
||||
const {
|
||||
isFolderTrustDialogOpen,
|
||||
discoveryResults: folderDiscoveryResults,
|
||||
@@ -1700,6 +1719,11 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (keyMatchers[Command.TOGGLE_BUFFER_MODE](key)) {
|
||||
toggleAlternateBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (keyMatchers[Command.QUIT](key)) {
|
||||
// If the user presses Ctrl+C, we want to cancel any ongoing requests.
|
||||
// This should happen regardless of the count.
|
||||
@@ -2204,8 +2228,11 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
};
|
||||
}, [config, refreshStatic]);
|
||||
|
||||
const showIsAlternateBufferHint = (historyManager.history.length > 15 || buffer.text.length > 200 || buffer.text.includes('\n')) && !isAlternateBuffer;
|
||||
|
||||
const uiState: UIState = useMemo(
|
||||
() => ({
|
||||
isAlternateBuffer,
|
||||
history: historyManager.history,
|
||||
historyManager,
|
||||
isThemeDialogOpen,
|
||||
@@ -2331,6 +2358,7 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
adminSettingsChanged,
|
||||
newAgents,
|
||||
showIsExpandableHint,
|
||||
showIsAlternateBufferHint,
|
||||
hintMode:
|
||||
config.isModelSteeringEnabled() && isToolExecuting(pendingHistoryItems),
|
||||
hintBuffer: '',
|
||||
@@ -2457,6 +2485,8 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
adminSettingsChanged,
|
||||
newAgents,
|
||||
showIsExpandableHint,
|
||||
showIsAlternateBufferHint,
|
||||
isAlternateBuffer,
|
||||
],
|
||||
);
|
||||
|
||||
@@ -2465,6 +2495,31 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
[setShowPrivacyNotice],
|
||||
);
|
||||
|
||||
const toggleAlternateBuffer = useCallback(() => {
|
||||
setIsAlternateBuffer(prev => {
|
||||
const next = !prev;
|
||||
if (next) {
|
||||
enterAlternateScreen();
|
||||
enableMouseEvents();
|
||||
disableLineWrapping();
|
||||
} else {
|
||||
exitAlternateScreen();
|
||||
disableMouseEvents();
|
||||
enableLineWrapping();
|
||||
writeToStdout('\x1b[2J\x1b[H');
|
||||
}
|
||||
process.stdout.emit('resize');
|
||||
|
||||
// Give a tick for resize to process, then trigger remount to force full redraw
|
||||
setImmediate(() => {
|
||||
refreshStatic();
|
||||
setForceRerenderKey((prev) => prev + 1);
|
||||
});
|
||||
|
||||
return next;
|
||||
});
|
||||
}, [setIsAlternateBuffer, refreshStatic, setForceRerenderKey]);
|
||||
|
||||
const uiActions: UIActions = useMemo(
|
||||
() => ({
|
||||
handleThemeSelect,
|
||||
@@ -2476,6 +2531,7 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
handleEditorSelect,
|
||||
exitEditorDialog,
|
||||
exitPrivacyNotice,
|
||||
toggleAlternateBuffer,
|
||||
closeSettingsDialog,
|
||||
closeModelDialog,
|
||||
openAgentConfigDialog,
|
||||
@@ -2614,6 +2670,7 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
config,
|
||||
historyManager,
|
||||
getPreferredEditor,
|
||||
toggleAlternateBuffer,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -142,4 +142,38 @@ describe('<StatusRow />', () => {
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('Tip: Test Tip');
|
||||
});
|
||||
|
||||
it('renders buffer toggle hint when showIsAlternateBufferHint is true', async () => {
|
||||
(useComposerStatus as Mock).mockReturnValue({
|
||||
isInteractiveShellWaiting: false,
|
||||
showLoadingIndicator: false,
|
||||
showTips: false,
|
||||
showWit: false,
|
||||
modeContentObj: null,
|
||||
showMinimalContext: false,
|
||||
});
|
||||
|
||||
const uiState: Partial<UIState> = {
|
||||
...defaultUiState,
|
||||
showIsAlternateBufferHint: true,
|
||||
};
|
||||
|
||||
const { lastFrame, waitUntilReady } = await renderWithProviders(
|
||||
<StatusRow
|
||||
showUiDetails={false}
|
||||
isNarrow={false}
|
||||
terminalWidth={100}
|
||||
hideContextSummary={false}
|
||||
hideUiDetailsForSuggestions={false}
|
||||
hasPendingActionRequired={false}
|
||||
/>,
|
||||
{
|
||||
width: 100,
|
||||
uiState,
|
||||
},
|
||||
);
|
||||
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toContain('[Alt+T] Switch to Full Screen');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -206,7 +206,12 @@ export const StatusRow: React.FC<StatusRowProps> = ({
|
||||
return uiState.currentTip;
|
||||
}
|
||||
|
||||
// 2. Shortcut Hint (Fallback)
|
||||
// 2. Buffer Toggle Hint
|
||||
if (uiState.showIsAlternateBufferHint) {
|
||||
return '[Alt+T] Switch to Full Screen';
|
||||
}
|
||||
|
||||
// 3. Shortcut Hint (Fallback)
|
||||
if (
|
||||
settings.merged.ui.showShortcutsHint &&
|
||||
!hideUiDetailsForSuggestions &&
|
||||
|
||||
@@ -205,6 +205,8 @@ const MAC_ALT_KEY_CHARACTER_MAP: Record<string, string> = {
|
||||
'\u03A9': 'z', // "Ω" Option+z
|
||||
'\u00B8': 'Z', // "¸" Option+Shift+z
|
||||
'\u2202': 'd', // "∂" delete word forward
|
||||
'\u2020': 't', // "†" toggle full screen buffer
|
||||
'\u00E5': 'a', // "å" Option+a for alternate buffer
|
||||
};
|
||||
|
||||
function nonKeyboardEventFilter(
|
||||
|
||||
@@ -78,6 +78,7 @@ export interface UIActions {
|
||||
setShortcutsHelpVisible: (visible: boolean) => void;
|
||||
setCleanUiDetailsVisible: (visible: boolean) => void;
|
||||
toggleCleanUiDetailsVisible: () => void;
|
||||
toggleAlternateBuffer: () => void;
|
||||
revealCleanUiDetailsTemporarily: (durationMs?: number) => void;
|
||||
handleWarning: (message: string) => void;
|
||||
setEmbeddedShellFocused: (value: boolean) => void;
|
||||
|
||||
@@ -118,6 +118,8 @@ export interface UIState {
|
||||
isEditorDialogOpen: boolean;
|
||||
showPrivacyNotice: boolean;
|
||||
corgiMode: boolean;
|
||||
isAlternateBuffer: boolean;
|
||||
showIsAlternateBufferHint: boolean;
|
||||
debugMessage: string;
|
||||
quittingMessages: HistoryItem[] | null;
|
||||
isSettingsDialogOpen: boolean;
|
||||
|
||||
@@ -11,49 +11,47 @@ import {
|
||||
isAlternateBufferEnabled,
|
||||
} from './useAlternateBuffer.js';
|
||||
import type { Config } from '@google/gemini-cli-core';
|
||||
import { useUIState } from '../contexts/UIStateContext.js';
|
||||
|
||||
vi.mock('../contexts/ConfigContext.js', () => ({
|
||||
useConfig: vi.fn(),
|
||||
}));
|
||||
vi.mock('../contexts/UIStateContext.js');
|
||||
|
||||
const mockUseConfig = vi.mocked(
|
||||
await import('../contexts/ConfigContext.js').then((m) => m.useConfig),
|
||||
);
|
||||
const mockUseUIState = vi.mocked(useUIState);
|
||||
|
||||
describe('useAlternateBuffer', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should return false when config.getUseAlternateBuffer returns false', async () => {
|
||||
mockUseConfig.mockReturnValue({
|
||||
getUseAlternateBuffer: () => false,
|
||||
} as unknown as ReturnType<typeof mockUseConfig>);
|
||||
it('should return false when uiState.isAlternateBuffer is false', async () => {
|
||||
mockUseUIState.mockReturnValue({
|
||||
isAlternateBuffer: false,
|
||||
} as unknown as ReturnType<typeof mockUseUIState>);
|
||||
|
||||
const { result } = await renderHook(() => useAlternateBuffer());
|
||||
expect(result.current).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true when config.getUseAlternateBuffer returns true', async () => {
|
||||
mockUseConfig.mockReturnValue({
|
||||
getUseAlternateBuffer: () => true,
|
||||
} as unknown as ReturnType<typeof mockUseConfig>);
|
||||
it('should return true when uiState.isAlternateBuffer is true', async () => {
|
||||
mockUseUIState.mockReturnValue({
|
||||
isAlternateBuffer: true,
|
||||
} as unknown as ReturnType<typeof mockUseUIState>);
|
||||
|
||||
const { result } = await renderHook(() => useAlternateBuffer());
|
||||
expect(result.current).toBe(true);
|
||||
});
|
||||
|
||||
it('should return the immutable config value, not react to settings changes', async () => {
|
||||
const mockConfig = {
|
||||
getUseAlternateBuffer: () => true,
|
||||
} as unknown as ReturnType<typeof mockUseConfig>;
|
||||
|
||||
mockUseConfig.mockReturnValue(mockConfig);
|
||||
it('should react to state changes', async () => {
|
||||
mockUseUIState.mockReturnValue({
|
||||
isAlternateBuffer: false,
|
||||
} as unknown as ReturnType<typeof mockUseUIState>);
|
||||
|
||||
const { result, rerender } = await renderHook(() => useAlternateBuffer());
|
||||
|
||||
// Value should remain true even after rerender
|
||||
expect(result.current).toBe(true);
|
||||
expect(result.current).toBe(false);
|
||||
|
||||
mockUseUIState.mockReturnValue({
|
||||
isAlternateBuffer: true,
|
||||
} as unknown as ReturnType<typeof mockUseUIState>);
|
||||
|
||||
rerender();
|
||||
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { useConfig } from '../contexts/ConfigContext.js';
|
||||
import { useUIState } from '../contexts/UIStateContext.js';
|
||||
import type { Config } from '@google/gemini-cli-core';
|
||||
|
||||
export const isAlternateBufferEnabled = (config: Config): boolean =>
|
||||
config.getUseAlternateBuffer();
|
||||
|
||||
// This is read from Config so that the UI reads the same value per application session
|
||||
// This is read from UIState so that the UI can toggle dynamically
|
||||
export const useAlternateBuffer = (): boolean => {
|
||||
const config = useConfig();
|
||||
return isAlternateBufferEnabled(config);
|
||||
const uiState = useUIState();
|
||||
return uiState.isAlternateBuffer;
|
||||
};
|
||||
|
||||
@@ -95,6 +95,7 @@ export enum Command {
|
||||
RESTART_APP = 'app.restart',
|
||||
SUSPEND_APP = 'app.suspend',
|
||||
SHOW_SHELL_INPUT_UNFOCUS_WARNING = 'app.showShellUnfocusWarning',
|
||||
TOGGLE_BUFFER_MODE = 'app.toggleBufferMode',
|
||||
|
||||
// Background Shell Controls
|
||||
BACKGROUND_SHELL_ESCAPE = 'background.escape',
|
||||
@@ -392,6 +393,7 @@ export const defaultKeyBindingConfig: KeyBindingConfig = new Map([
|
||||
[Command.RESTART_APP, [new KeyBinding('r'), new KeyBinding('shift+r')]],
|
||||
[Command.SUSPEND_APP, [new KeyBinding('ctrl+z')]],
|
||||
[Command.SHOW_SHELL_INPUT_UNFOCUS_WARNING, [new KeyBinding('tab')]],
|
||||
[Command.TOGGLE_BUFFER_MODE, [new KeyBinding('alt+a')]],
|
||||
|
||||
// Background Shell Controls
|
||||
[Command.BACKGROUND_SHELL_ESCAPE, [new KeyBinding('escape')]],
|
||||
@@ -609,6 +611,7 @@ export const commandDescriptions: Readonly<Record<Command, string>> = {
|
||||
[Command.SHOW_IDE_CONTEXT_DETAIL]: 'Show IDE context details.',
|
||||
[Command.TOGGLE_MARKDOWN]: 'Toggle Markdown rendering.',
|
||||
[Command.TOGGLE_COPY_MODE]: 'Toggle copy mode when in alternate buffer mode.',
|
||||
[Command.TOGGLE_BUFFER_MODE]: 'Toggle between regular and full screen (alternate buffer) mode.',
|
||||
[Command.TOGGLE_YOLO]: 'Toggle YOLO (auto-approval) mode for tool calls.',
|
||||
[Command.CYCLE_APPROVAL_MODE]:
|
||||
'Cycle through approval modes: default (prompt), auto_edit (auto-approve edits), and plan (read-only). Plan mode is skipped when the agent is busy.',
|
||||
|
||||
Reference in New Issue
Block a user