From 3406dc5b2eb05f9f24dc8be75df7107d158d852a Mon Sep 17 00:00:00 2001 From: kevinjwang1 Date: Wed, 26 Nov 2025 19:22:26 +0000 Subject: [PATCH] Add consent flag to Link command (#13832) --- .../cli/src/commands/extensions/link.test.ts | 8 +++++++ packages/cli/src/commands/extensions/link.ts | 22 +++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/commands/extensions/link.test.ts b/packages/cli/src/commands/extensions/link.test.ts index 252d704d53..631aee629b 100644 --- a/packages/cli/src/commands/extensions/link.test.ts +++ b/packages/cli/src/commands/extensions/link.test.ts @@ -138,6 +138,7 @@ describe('extensions link command', () => { describe('builder', () => { interface MockYargs { positional: Mock; + option: Mock; check: Mock; } @@ -145,6 +146,7 @@ describe('extensions link command', () => { beforeEach(() => { yargsMock = { positional: vi.fn().mockReturnThis(), + option: vi.fn().mockReturnThis(), check: vi.fn().mockReturnThis(), }; }); @@ -157,6 +159,12 @@ describe('extensions link command', () => { describe: 'The name of the extension to link.', type: 'string', }); + expect(yargsMock.option).toHaveBeenCalledWith('consent', { + describe: + 'Acknowledge the security risks of installing an extension and skip the confirmation prompt.', + type: 'boolean', + default: false, + }); expect(yargsMock.check).toHaveBeenCalled(); }); }); diff --git a/packages/cli/src/commands/extensions/link.ts b/packages/cli/src/commands/extensions/link.ts index 845475e551..62bb9dc5a6 100644 --- a/packages/cli/src/commands/extensions/link.ts +++ b/packages/cli/src/commands/extensions/link.ts @@ -11,7 +11,10 @@ import { } from '@google/gemini-cli-core'; import { getErrorMessage } from '../../utils/errors.js'; -import { requestConsentNonInteractive } from '../../config/extensions/consent.js'; +import { + INSTALL_WARNING_MESSAGE, + requestConsentNonInteractive, +} from '../../config/extensions/consent.js'; import { ExtensionManager } from '../../config/extension-manager.js'; import { loadSettings } from '../../config/settings.js'; import { promptForSetting } from '../../config/extensions/extensionSettings.js'; @@ -19,6 +22,7 @@ import { exitCli } from '../utils.js'; interface InstallArgs { path: string; + consent?: boolean; } export async function handleLink(args: InstallArgs) { @@ -27,10 +31,17 @@ export async function handleLink(args: InstallArgs) { source: args.path, type: 'link', }; + const requestConsent = args.consent + ? () => Promise.resolve(true) + : requestConsentNonInteractive; + if (args.consent) { + debugLogger.log('You have consented to the following:'); + debugLogger.log(INSTALL_WARNING_MESSAGE); + } const workspaceDir = process.cwd(); const extensionManager = new ExtensionManager({ workspaceDir, - requestConsent: requestConsentNonInteractive, + requestConsent, requestSetting: promptForSetting, settings: loadSettings(workspaceDir).merged, }); @@ -56,10 +67,17 @@ export const linkCommand: CommandModule = { describe: 'The name of the extension to link.', type: 'string', }) + .option('consent', { + describe: + 'Acknowledge the security risks of installing an extension and skip the confirmation prompt.', + type: 'boolean', + default: false, + }) .check((_) => true), handler: async (argv) => { await handleLink({ path: argv['path'] as string, + consent: argv['consent'] as boolean | undefined, }); await exitCli(); },