CLI terminal command handling to remove cd#4034
Open
DonJayamanne wants to merge 1 commit intomainfrom
Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adjusts how Copilot CLI shell commands are presented to users by stripping redundant cd <workingDirectory> && (and PowerShell equivalents) when the cd target matches the known working directory, aligning with vscode#297967.
Changes:
- Exported and reused
getCdPresentationOverridesto derive a user-friendly command line without a redundantcdprefix. - Updated Copilot CLI tool-invocation formatting to apply the
cd-stripping presentation logic. - Added/updated unit tests to cover bash vs PowerShell patterns and workingDirectory matching behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/extension/agents/copilotcli/node/permissionHelpers.ts | Uses getCdPresentationOverrides to present a stripped command in terminal permission confirmations (with OS defaulting). |
| src/extension/agents/copilotcli/node/test/permissionHelpers.spec.ts | Adds coverage for stripping/keeping cd/Set-Location prefixes based on workingDirectory and Windows mode. |
| src/extension/agents/copilotcli/common/copilotCLITools.ts | Exports getCdPresentationOverrides and applies it while formatting shell tool invocation data. |
| src/extension/agents/copilotcli/common/test/copilotCLITools.spec.ts | Updates expectations around command-line data when cd stripping applies. |
Comments suppressed due to low confidence (4)
src/extension/agents/copilotcli/common/test/copilotCLITools.spec.ts:601
- This assertion assumes
commandLine.originalis stripped, butChatTerminalToolInvocationDatadocuments stripping viapresentationOverrideswhile keepingoriginalintact. Update this test to reflect the corrected behavior (full command inoriginal, stripped command inpresentationOverrides).
const data = completed.toolSpecificData as any;
expect(data.commandLine.original).toBe('make build');
expect(data.presentationOverrides).toEqual({ commandLine: 'make build' });
expect(data.state.exitCode).toBe(0);
src/extension/agents/copilotcli/common/copilotCLITools.ts:836
- On Windows,
isEqualhere is case-sensitive (it’s bound toextUri), socd C:\Workspacevs workingDirectoryc:\workspacewon’t match and thecdprefix won’t be stripped. Since this is file-path matching, consider using a casing-insensitive comparison (e.g.extUriBiasedIgnorePathCase.isEqual) or otherwise normalizing drive-letter/path casing before comparing.
export function getCdPresentationOverrides(commandLine: string, isPowershell: boolean, workingDirectory?: URI): { commandLine: string } | undefined {
const cdPrefix = extractCdPrefix(commandLine, isPowershell);
if (!cdPrefix || !workingDirectory) {
return undefined;
}
const cdUri = URI.file(cdPrefix.directory);
if (isEqual(cdUri, workingDirectory)) {
return { commandLine: cdPrefix.command };
src/extension/agents/copilotcli/common/copilotCLITools.ts:853
ChatTerminalToolInvocationData.commandLine.originalis documented as the original/executed command, whilepresentationOverrides.commandLineis the UI-only stripped form. Overwritingoriginalwith the stripped command breaks that contract and can lose the real command for auditing/fallback UI. KeepcommandLine.originalascommand(full input) and only setpresentationOverrideswhen thecdprefix matches.
This issue also appears on line 863 of the same file.
const presentationOverrides = getCdPresentationOverrides(command, isPowershell, workingDirectory);
invocation.invocationMessage = args.description ? new MarkdownString(args.description) : '';
invocation.toolSpecificData = {
commandLine: {
original: presentationOverrides?.commandLine ?? command
},
language: isPowershell ? 'powershell' : 'bash',
presentationOverrides
} as ChatTerminalToolInvocationData;
src/extension/agents/copilotcli/common/copilotCLITools.ts:869
- Same issue on completion:
commandLine.originalshould remaintoolCall.arguments.commandand not be replaced by the presentation override. UsepresentationOverrides.commandLinefor the stripped display value only.
const presentationOverrides = getCdPresentationOverrides(toolCall.arguments.command, isPowershell, workingDirectory);
const toolSpecificData: ChatTerminalToolInvocationData = {
commandLine: {
original: presentationOverrides?.commandLine ?? toolCall.arguments.command
},
language: isPowershell ? 'powershell' : 'bash',
presentationOverrides,
connor4312
approved these changes
Feb 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes microsoft/vscode#297967