Merge pull request #3 from devNull-bootloader/feat/initial-vscode-extension

fix: address review feedback for launcher behavior and links
This commit is contained in:
Urvish Lanje
2026-04-02 19:53:21 +02:00
committed by GitHub
2 changed files with 78 additions and 17 deletions

View File

@@ -70,8 +70,8 @@
}, },
"openclaude.useOpenAIShim": { "openclaude.useOpenAIShim": {
"type": "boolean", "type": "boolean",
"default": true, "default": false,
"description": "Set CLAUDE_CODE_USE_OPENAI=1 in launched OpenClaude terminals." "description": "Optionally set CLAUDE_CODE_USE_OPENAI=1 in launched OpenClaude terminals."
} }
} }
}, },
@@ -96,7 +96,7 @@
], ],
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/devNull-bootloader/openclaude" "url": "https://github.com/Gitlawb/openclaude"
}, },
"license": "MIT" "license": "MIT"
} }

View File

@@ -1,16 +1,62 @@
const vscode = require('vscode'); const vscode = require('vscode');
const crypto = require('crypto'); const crypto = require('crypto');
const { exec } = require('child_process');
const { promisify } = require('util');
function launchOpenClaude() { const execAsync = promisify(exec);
const OPENCLAUDE_REPO_URL = 'https://github.com/Gitlawb/openclaude';
async function isCommandAvailable(command) {
try {
if (!command) {
return false;
}
if (process.platform === 'win32') {
await execAsync(`where ${command}`);
} else {
await execAsync(`command -v ${command}`);
}
return true;
} catch {
return false;
}
}
function getExecutableFromCommand(command) {
return command.trim().split(/\s+/)[0];
}
async function launchOpenClaude() {
const configured = vscode.workspace.getConfiguration('openclaude'); const configured = vscode.workspace.getConfiguration('openclaude');
const launchCommand = configured.get('launchCommand', 'openclaude'); const launchCommand = configured.get('launchCommand', 'openclaude');
const terminalName = configured.get('terminalName', 'OpenClaude'); const terminalName = configured.get('terminalName', 'OpenClaude');
const shimEnabled = configured.get('useOpenAIShim', false);
const executable = getExecutableFromCommand(launchCommand);
const installed = await isCommandAvailable(executable);
if (!installed) {
const action = await vscode.window.showErrorMessage(
`OpenClaude command not found: ${executable}. Install it with: npm install -g @gitlawb/openclaude`,
'Open Repository'
);
if (action === 'Open Repository') {
await vscode.env.openExternal(vscode.Uri.parse(OPENCLAUDE_REPO_URL));
}
return;
}
const env = {};
if (shimEnabled) {
env.CLAUDE_CODE_USE_OPENAI = '1';
}
const terminal = vscode.window.createTerminal({ const terminal = vscode.window.createTerminal({
name: terminalName, name: terminalName,
env: { env,
CLAUDE_CODE_USE_OPENAI: configured.get('useOpenAIShim', true) ? '1' : undefined,
},
}); });
terminal.show(true); terminal.show(true);
@@ -18,18 +64,30 @@ function launchOpenClaude() {
} }
class OpenClaudeControlCenterProvider { class OpenClaudeControlCenterProvider {
resolveWebviewView(webviewView) { async resolveWebviewView(webviewView) {
webviewView.webview.options = { enableScripts: true }; webviewView.webview.options = { enableScripts: true };
webviewView.webview.html = this.getHtml(webviewView.webview); const configured = vscode.workspace.getConfiguration('openclaude');
const launchCommand = configured.get('launchCommand', 'openclaude');
const executable = getExecutableFromCommand(launchCommand);
const installed = await isCommandAvailable(executable);
const shimEnabled = configured.get('useOpenAIShim', false);
const shortcut = process.platform === 'darwin' ? 'Cmd+Shift+P' : 'Ctrl+Shift+P';
webviewView.webview.html = this.getHtml(webviewView.webview, {
installed,
shimEnabled,
shortcut,
executable,
});
webviewView.webview.onDidReceiveMessage(async (message) => { webviewView.webview.onDidReceiveMessage(async (message) => {
if (message?.type === 'launch') { if (message?.type === 'launch') {
launchOpenClaude(); await launchOpenClaude();
return; return;
} }
if (message?.type === 'docs') { if (message?.type === 'docs') {
await vscode.env.openExternal(vscode.Uri.parse('https://github.com/devNull-bootloader/openclaude')); await vscode.env.openExternal(vscode.Uri.parse(OPENCLAUDE_REPO_URL));
return; return;
} }
@@ -39,8 +97,10 @@ class OpenClaudeControlCenterProvider {
}); });
} }
getHtml(webview) { getHtml(webview, status) {
const nonce = crypto.randomBytes(16).toString('base64'); const nonce = crypto.randomBytes(16).toString('base64');
const runtimeLabel = status.installed ? 'available' : 'missing';
const shimLabel = status.shimEnabled ? 'enabled (CLAUDE_CODE_USE_OPENAI=1)' : 'disabled';
return `<!DOCTYPE html> return `<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@@ -216,8 +276,9 @@ class OpenClaudeControlCenterProvider {
<div class="terminal-box"> <div class="terminal-box">
<div class="terminal-row"><span class="prompt">$</span> openclaude --status</div> <div class="terminal-row"><span class="prompt">$</span> openclaude --status</div>
<div class="terminal-row">runtime: active</div> <div class="terminal-row">runtime: ${runtimeLabel}</div>
<div class="terminal-row">shim: CLAUDE_CODE_USE_OPENAI=1</div> <div class="terminal-row">shim: ${shimLabel}</div>
<div class="terminal-row">command: ${status.executable}</div>
<div class="terminal-row"><span class="prompt">$</span> <span class="cursor">awaiting command</span></div> <div class="terminal-row"><span class="prompt">$</span> <span class="cursor">awaiting command</span></div>
</div> </div>
@@ -228,7 +289,7 @@ class OpenClaudeControlCenterProvider {
</div> </div>
<div class="hint"> <div class="hint">
Quick trigger: use <code>Ctrl+Shift+P</code> and run OpenClaude commands from anywhere. Quick trigger: use <code>${status.shortcut}</code> and run OpenClaude commands from anywhere.
</div> </div>
</div> </div>
</div> </div>
@@ -249,11 +310,11 @@ class OpenClaudeControlCenterProvider {
*/ */
function activate(context) { function activate(context) {
const startCommand = vscode.commands.registerCommand('openclaude.start', async () => { const startCommand = vscode.commands.registerCommand('openclaude.start', async () => {
launchOpenClaude(); await launchOpenClaude();
}); });
const openDocsCommand = vscode.commands.registerCommand('openclaude.openDocs', async () => { const openDocsCommand = vscode.commands.registerCommand('openclaude.openDocs', async () => {
await vscode.env.openExternal(vscode.Uri.parse('https://github.com/devNull-bootloader/openclaude')); await vscode.env.openExternal(vscode.Uri.parse(OPENCLAUDE_REPO_URL));
}); });
const openUiCommand = vscode.commands.registerCommand('openclaude.openControlCenter', async () => { const openUiCommand = vscode.commands.registerCommand('openclaude.openControlCenter', async () => {