Skip to content

Commit f7684dc

Browse files
committed
Release 0.6.0: per-agent Update button, accurate updates, WSL option
- Add a per-agent Update button in the sidebar (next to Launch) for agents that have a known update command: codex update, copilot update, kilo upgrade, hermes update, claude update, npm reinstall for Crush. - New updateCommand agent field with each CLI's official update command. autoUpdate now runs it instead of a blind reinstall; self-updating CLIs run nothing. - superCli.autoUpdate is now off by default (most CLIs self-update). - New superCli.useWsl: on Windows, open agents in a WSL terminal (native VS Code support); under WSL agents use their Unix install/update commands.
1 parent 1de6ed0 commit f7684dc

10 files changed

Lines changed: 158 additions & 16 deletions

File tree

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@
33
All notable changes to this project are documented here. The format is based on
44
[Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
55

6+
## [0.6.0]
7+
8+
- **Per-agent Update button.** Each sidebar agent that has a known update command now shows an update
9+
button next to Launch, which runs the CLI's official update (e.g. `codex update`, `copilot update`,
10+
`kilo upgrade`, `hermes update`, `claude update`, npm reinstall for Crush).
11+
- **Accurate updates.** New `updateCommand` agent field carries each CLI's official update command.
12+
`superCli.autoUpdate` now runs that command instead of a blind reinstall; CLIs that update
13+
themselves (OpenCode, Cursor, Droid, MiMo Code, Command Code) run nothing.
14+
- **`superCli.autoUpdate` is now off by default** — most CLIs already self-update.
15+
- **`superCli.useWsl`** (new): on Windows, open agents in a WSL terminal (native VS Code support);
16+
under WSL the agents use their Unix install/update commands.
17+
618
## [0.5.0]
719

820
- New `superCli.autoUpdate` setting (default on): each coding agent CLI is updated to its latest

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ You can also open the Extensions view in VS Code (or Cursor, Antigravity, Windsu
4040
retired by Google and replaced by Antigravity.)
4141
- **Add your own, no code required.** Define new agents in `settings.json`. The sidebar updates
4242
automatically.
43+
- **Update from the sidebar.** Agents with a known update command show an update button next to
44+
Launch, which runs the CLI's official update (e.g. `codex update`, `kilo upgrade`, `hermes update`).
45+
CLIs that update themselves don't show one. The optional `superCli.autoUpdate` setting can run that
46+
update on launch.
4347
- **Guided install.** If a built-in CLI isn't found, Super CLI offers to install it with its official
4448
command after explicit confirmation — npm for Claude Code, Codex, Copilot, Kilo, OpenCode, Command
4549
Code, Droid, Crush and MiMo Code, and the official installer script for Grok, Antigravity, Cursor
@@ -86,6 +90,10 @@ reuses a built-in `id` — overrides that built-in (for example to point at a cu
8690
"defaults": { "autoInstallExtension": false } }`.
8791
- `env` — optional environment variables set for the agent's terminal, e.g. to opt out of a CLI's
8892
IDE-extension auto-install via its own variable: `{ "CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL": "1" }`.
93+
- `updateCommand` — optional command to update the CLI (its official `update`/`upgrade` command, or
94+
an npm reinstall). Adds an update button next to the agent in the sidebar, and is used by
95+
`superCli.autoUpdate`. Like `installCommand`, it can be a string or an object with `unix`/`windows`
96+
keys.
8997

9098
Only the user (global) value of `superCli.agents` is used; workspace overrides are ignored so that
9199
an untrusted repository cannot inject commands.
@@ -97,7 +105,8 @@ an untrusted repository cannot inject commands.
97105
| `superCli.agents` | `[]` | Your agents (added to or overriding the built-ins). |
98106
| `superCli.useBuiltins` | `true` | Include the built-in agent presets. |
99107
| `superCli.terminalLocation` | `beside` | Open the terminal `beside` the editor or in the `panel`. |
100-
| `superCli.autoUpdate` | `true` | Update each CLI to its latest version on launch (npm reinstall or the official installer script). |
108+
| `superCli.autoUpdate` | `false` | Run each CLI's update command on launch (when it has one). Off by default — most CLIs self-update. |
109+
| `superCli.useWsl` | `false` | On Windows, open agents in a WSL terminal instead of the default shell. Ignored on macOS/Linux. |
101110

102111
Run **Super CLI: Open Settings** from the sidebar or the command palette to jump straight to these
103112
settings.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"displayName": "Super CLI",
44
"description": "One VS Code extension to launch any coding agent CLI (Claude Code, Codex, Copilot, Antigravity, and your own) from a single side terminal.",
55
"publisher": "mikesoft",
6-
"version": "0.5.0",
6+
"version": "0.6.0",
77
"repository": {
88
"type": "git",
99
"url": "https://github.com/TheStreamCode/super-cli.git"
@@ -98,6 +98,12 @@
9898
"category": "Super CLI",
9999
"icon": "$(play)"
100100
},
101+
{
102+
"command": "superCli.updateAgent",
103+
"title": "Update Agent",
104+
"category": "Super CLI",
105+
"icon": "$(arrow-circle-up)"
106+
},
101107
{
102108
"command": "superCli.refresh",
103109
"title": "Refresh Agents",
@@ -133,15 +139,24 @@
133139
"view/item/context": [
134140
{
135141
"command": "superCli.launchAgent",
136-
"when": "view == superCli.agents && viewItem == agent",
137-
"group": "inline"
142+
"when": "view == superCli.agents && viewItem =~ /agent/",
143+
"group": "inline@1"
144+
},
145+
{
146+
"command": "superCli.updateAgent",
147+
"when": "view == superCli.agents && viewItem == agent-updatable",
148+
"group": "inline@2"
138149
}
139150
],
140151
"commandPalette": [
141152
{
142153
"command": "superCli.launchAgent",
143154
"when": "false"
144155
},
156+
{
157+
"command": "superCli.updateAgent",
158+
"when": "false"
159+
},
145160
{
146161
"command": "superCli.refresh",
147162
"when": "false"
@@ -230,6 +245,25 @@
230245
"additionalProperties": {
231246
"type": "string"
232247
}
248+
},
249+
"updateCommand": {
250+
"description": "Optional command to update the CLI to its latest version (its official update/upgrade command, or an npm reinstall). Shown as an update button in the sidebar, and used by superCli.autoUpdate. Use a string, or an object with \"unix\" and \"windows\" keys for OS-specific commands.",
251+
"oneOf": [
252+
{
253+
"type": "string"
254+
},
255+
{
256+
"type": "object",
257+
"properties": {
258+
"unix": {
259+
"type": "string"
260+
},
261+
"windows": {
262+
"type": "string"
263+
}
264+
}
265+
}
266+
]
233267
}
234268
}
235269
}
@@ -256,9 +290,15 @@
256290
},
257291
"superCli.autoUpdate": {
258292
"type": "boolean",
259-
"default": true,
293+
"default": false,
294+
"scope": "window",
295+
"description": "Run each coding agent CLI's update command on launch, when it has one. Off by default, since most CLIs already update themselves. Enable to have Super CLI update them before launching."
296+
},
297+
"superCli.useWsl": {
298+
"type": "boolean",
299+
"default": false,
260300
"scope": "window",
261-
"description": "Update each coding agent CLI to its latest version on launch, using its install command (npm reinstall, or the official installer script). Disable to launch without updating."
301+
"description": "On Windows, open coding agents in a WSL terminal instead of the default shell (uses VS Code's native WSL support). Ignored on macOS and Linux."
262302
}
263303
}
264304
}

src/agents.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export interface Agent {
1717
autoInstall?: boolean;
1818
ensureConfig?: EnsureConfig;
1919
env?: Record<string, string>;
20+
updateCommand?: InstallCommand;
2021
}
2122

2223
/** Built-in agent presets shipped with the extension. Users override them by reusing an id. */
@@ -28,6 +29,7 @@ export const BUILTIN_AGENTS: readonly Agent[] = [
2829
icon: 'sparkle',
2930
installCommand: 'npm install -g @anthropic-ai/claude-code',
3031
autoInstall: true,
32+
updateCommand: 'claude update',
3133
// Super CLI is one extension for every CLI, so skip Claude Code's IDE extension
3234
// auto-install using its own official environment variable.
3335
env: { CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL: '1' },
@@ -39,6 +41,7 @@ export const BUILTIN_AGENTS: readonly Agent[] = [
3941
icon: 'rocket',
4042
installCommand: 'npm install -g @openai/codex',
4143
autoInstall: true,
44+
updateCommand: 'codex update',
4245
},
4346
{
4447
id: 'copilot',
@@ -47,6 +50,7 @@ export const BUILTIN_AGENTS: readonly Agent[] = [
4750
icon: 'github',
4851
installCommand: 'npm install -g @github/copilot',
4952
autoInstall: true,
53+
updateCommand: 'copilot update',
5054
},
5155
{
5256
id: 'grok',
@@ -64,6 +68,7 @@ export const BUILTIN_AGENTS: readonly Agent[] = [
6468
icon: 'terminal',
6569
installCommand: 'npm install -g @kilocode/cli',
6670
autoInstall: true,
71+
updateCommand: 'kilo upgrade',
6772
},
6873
{
6974
id: 'antigravity',
@@ -126,6 +131,7 @@ export const BUILTIN_AGENTS: readonly Agent[] = [
126131
icon: 'flame',
127132
installCommand: 'npm install -g @charmland/crush',
128133
autoInstall: true,
134+
updateCommand: 'npm install -g @charmland/crush',
129135
},
130136
{
131137
id: 'hermes',
@@ -135,6 +141,7 @@ export const BUILTIN_AGENTS: readonly Agent[] = [
135141
// Official shell installer (no npm package).
136142
installCommand: { unix: 'curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash' },
137143
autoInstall: true,
144+
updateCommand: 'hermes update',
138145
},
139146
{
140147
id: 'mimo',

src/extension.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as vscode from 'vscode';
22
import { type Agent, BUILTIN_AGENTS, resolveAgents } from './agents.js';
33
import { AgentTreeDataProvider } from './tree.js';
4-
import { launchAgent, openExtensionSettings } from './terminal.js';
4+
import { launchAgent, openExtensionSettings, updateAgent } from './terminal.js';
55

66
const SETTINGS_NAMESPACE = 'superCli';
77

@@ -59,6 +59,14 @@ export function activate(context: vscode.ExtensionContext): void {
5959
await launchAgent(agent, context, terminalSequence++);
6060
});
6161

62+
const updateAgentCommand = vscode.commands.registerCommand('superCli.updateAgent', async (agent?: Agent) => {
63+
if (!agent) {
64+
return;
65+
}
66+
67+
await updateAgent(agent, context);
68+
});
69+
6270
const refreshCommand = vscode.commands.registerCommand('superCli.refresh', () => {
6371
treeProvider.refresh();
6472
});
@@ -77,6 +85,7 @@ export function activate(context: vscode.ExtensionContext): void {
7785
treeView,
7886
launchCommand,
7987
launchAgentCommand,
88+
updateAgentCommand,
8089
refreshCommand,
8190
openSettingsCommand,
8291
configWatcher,

src/terminal.ts

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ function startGuidedInstall(agent: Agent, installCommand: string): void {
118118
installTerminal.sendText(installCommand, true);
119119
}
120120

121-
async function handleMissingAgent(agent: Agent, context: vscode.ExtensionContext): Promise<void> {
122-
const installCommand = resolveInstallCommand(agent.installCommand, process.platform);
121+
async function handleMissingAgent(agent: Agent, context: vscode.ExtensionContext, platform: string): Promise<void> {
122+
const installCommand = resolveInstallCommand(agent.installCommand, platform);
123123

124124
if (installCommand && agent.autoInstall) {
125125
const selection = await vscode.window.showWarningMessage(
@@ -154,14 +154,15 @@ function watchForMissingAgent(
154154
agent: Agent,
155155
context: vscode.ExtensionContext,
156156
runCommand: string,
157+
platform: string,
157158
): void {
158159
executeCommandWithOptionalShellIntegration(
159160
terminal,
160161
runCommand,
161162
context,
162163
async (endEvent, output) => {
163164
if (shouldPromptToInstall(agent.command, endEvent.exitCode, output)) {
164-
await handleMissingAgent(agent, context);
165+
await handleMissingAgent(agent, context, platform);
165166
}
166167
},
167168
);
@@ -230,8 +231,11 @@ export async function launchAgent(agent: Agent, context: vscode.ExtensionContext
230231

231232
const configuration = vscode.workspace.getConfiguration(SETTINGS_NAMESPACE);
232233
const location = configuration.get<string>('terminalLocation', 'beside');
233-
const autoUpdate = configuration.get<boolean>('autoUpdate', true);
234-
const updateCommand = autoUpdate ? resolveInstallCommand(agent.installCommand, process.platform) : undefined;
234+
// WSL only applies on Windows; under WSL the agents use their Unix install/update commands.
235+
const useWsl = configuration.get<boolean>('useWsl', false) && process.platform === 'win32';
236+
const platform = useWsl ? 'linux' : process.platform;
237+
const autoUpdate = configuration.get<boolean>('autoUpdate', false);
238+
const updateCommand = autoUpdate ? resolveInstallCommand(agent.updateCommand, platform) : undefined;
235239
const launchCommand = buildLaunchCommand(command, updateCommand);
236240
const cwd = resolveTerminalCwd(vscode.window.activeTextEditor, vscode.workspace);
237241

@@ -240,8 +244,46 @@ export async function launchAgent(agent: Agent, context: vscode.ExtensionContext
240244
location: location === 'panel' ? vscode.TerminalLocation.Panel : { viewColumn: vscode.ViewColumn.Beside },
241245
cwd,
242246
env: agent.env,
247+
shellPath: useWsl ? 'wsl.exe' : undefined,
243248
});
244249
terminal.show();
245-
watchForMissingAgent(terminal, agent, context, launchCommand);
250+
watchForMissingAgent(terminal, agent, context, launchCommand, platform);
246251
void vscode.window.setStatusBarMessage(`Started ${agent.label}`, 2500);
247252
}
253+
254+
/** Runs the agent's official update command in a dedicated terminal (without launching the agent). */
255+
export async function updateAgent(agent: Agent, context: vscode.ExtensionContext): Promise<void> {
256+
if (!vscode.workspace.isTrusted) {
257+
const selection = await vscode.window.showWarningMessage(
258+
`Super CLI runs terminal commands in the current workspace. Trust this workspace before updating ${agent.label}.`,
259+
'Manage Workspace Trust',
260+
);
261+
262+
if (selection === 'Manage Workspace Trust') {
263+
await vscode.commands.executeCommand('workbench.trust.manage');
264+
}
265+
266+
return;
267+
}
268+
269+
const useWsl = vscode.workspace.getConfiguration(SETTINGS_NAMESPACE).get<boolean>('useWsl', false) && process.platform === 'win32';
270+
const platform = useWsl ? 'linux' : process.platform;
271+
const updateCommand = resolveInstallCommand(agent.updateCommand, platform);
272+
273+
if (!updateCommand) {
274+
void vscode.window.showInformationMessage(`${agent.label} has no configured update command — it likely updates itself.`);
275+
return;
276+
}
277+
278+
const cwd = resolveTerminalCwd(vscode.window.activeTextEditor, vscode.workspace);
279+
const terminal = vscode.window.createTerminal({
280+
name: `Update ${agent.label}`,
281+
location: vscode.TerminalLocation.Panel,
282+
cwd,
283+
env: agent.env,
284+
shellPath: useWsl ? 'wsl.exe' : undefined,
285+
});
286+
terminal.show();
287+
terminal.sendText(updateCommand, true);
288+
void vscode.window.setStatusBarMessage(`Updating ${agent.label}`, 2500);
289+
}

src/tree.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export class AgentTreeDataProvider implements vscode.TreeDataProvider<Agent> {
3030
item.id = agent.id;
3131
item.description = agent.command;
3232
item.tooltip = `Launch ${agent.label} (${agent.command})`;
33-
item.contextValue = 'agent';
33+
item.contextValue = agent.updateCommand ? 'agent-updatable' : 'agent';
3434
item.iconPath = new vscode.ThemeIcon(normalizeIconId(agent.icon) ?? 'terminal');
3535
item.command = {
3636
command: 'superCli.launchAgent',

test/agents.test.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,28 @@ test('OpenCode ships as a built-in preset', () => {
5353
assert.equal(opencode.installCommand, 'npm install -g opencode-ai');
5454
});
5555

56+
test('agents with a known update command carry their official one', () => {
57+
const expected = {
58+
claude: 'claude update',
59+
codex: 'codex update',
60+
copilot: 'copilot update',
61+
kilo: 'kilo upgrade',
62+
hermes: 'hermes update',
63+
crush: 'npm install -g @charmland/crush',
64+
};
65+
for (const [id, cmd] of Object.entries(expected)) {
66+
const agent = BUILTIN_AGENTS.find((a) => a.id === id);
67+
assert.equal(agent.updateCommand, cmd, id);
68+
}
69+
});
70+
71+
test('self-updating CLIs have no manual update command', () => {
72+
for (const id of ['opencode', 'cursor', 'droid', 'mimo', 'command-code']) {
73+
const agent = BUILTIN_AGENTS.find((a) => a.id === id);
74+
assert.equal(agent.updateCommand, undefined, id);
75+
}
76+
});
77+
5678
test('Claude Code skips its IDE extension auto-install via env', () => {
5779
const claude = BUILTIN_AGENTS.find((a) => a.id === 'claude');
5880
assert.equal(claude.env.CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL, '1');

test/metadata.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ test('package declares the launcher commands', () => {
4545
assert.deepEqual(commands, [
4646
'superCli.launch',
4747
'superCli.launchAgent',
48+
'superCli.updateAgent',
4849
'superCli.refresh',
4950
'superCli.openSettings',
5051
]);

0 commit comments

Comments
 (0)