VS Code extension providing PyCharm-style Python run configuration management with a GUI editor. Built with TypeScript, bundled with esbuild.
src/
├── extension.ts # Entry point - activate/deactivate
├── types.ts # RunConfiguration interface, enums, helpers
├── configStore.ts # CRUD for .vscode/python-run-configs.json
├── variableResolver.ts # ${workspaceFolder}, ${file}, ${env:VAR} expansion
├── interpreterResolver.ts # Python interpreter resolution
├── runner.ts # Build DebugConfiguration, launch via debugpy
├── commands.ts # All 12 command registrations
├── statusBar.ts # Status bar: config selector + run/debug buttons
├── treeView/
│ ├── configTreeProvider.ts # TreeDataProvider for sidebar panel
│ └── configTreeItem.ts # TreeItem with contextValue for menus
└── webview/
├── configEditorProvider.ts # WebviewPanel management + message passing
└── configEditorHtml.ts # Full HTML generation with inline CSS/JS
RunConfiguration stored in .vscode/python-run-configs.json:
id(UUID) - stable reference surviving renamesname- user-friendly labelrunType- "script" | "module"script/module- execution targetinterpreter- "selected" (Python ext) or custom pathargs- string arraycwd- working directory with variable supportenv- key-value environment variablesterminal- "integrated" | "external" | "internalConsole"runMode- "run" | "debug"
Active config ID stored in workspaceState (per-user, not committed to VCS).
- debugpy type (not deprecated
python) for debug configurations - UUID id on configs for stable references
- esbuild bundler per VS Code docs recommendation
- Vanilla HTML + CSS variables in webview (no framework dependency)
- FileSystemWatcher on config file for external change detection
- Inline webview script with CSP nonce for security
- @vscode-elements not used in final implementation - vanilla HTML form elements with VS Code CSS variables provide sufficient native look
| Command | Description | Source |
|---|---|---|
charmrun.runConfiguration |
Run active config | Status bar / palette |
charmrun.debugConfiguration |
Debug active config | Status bar / palette |
charmrun.runCurrentFile |
Run open .py file | Palette |
charmrun.debugCurrentFile |
Debug open .py file | Palette |
charmrun.createConfiguration |
Open editor for new config | Tree title / palette |
charmrun.editConfiguration |
Edit existing config | Tree context / palette |
charmrun.deleteConfiguration |
Delete with confirmation | Tree context / palette |
charmrun.duplicateConfiguration |
Copy config | Tree context |
charmrun.selectActiveConfig |
QuickPick selector | Status bar / palette |
charmrun.refreshConfigurations |
Refresh tree view | Tree title |
charmrun.runConfigFromTree |
Run specific config | Tree inline button |
charmrun.debugConfigFromTree |
Debug specific config | Tree inline button |
- Custom view container "charmrun-explorer" with play icon
- Flat list of configs across workspace folders
- Inline run/debug buttons per item
- Context menu: Edit, Duplicate, Delete
- Welcome view when no configs exist
- Full HTML form with VS Code theme CSS variables
- Fields: Name, Run Type, Script/Module, Interpreter, Args, CWD, Env Vars, Terminal, Run Mode
- Browse buttons for file/folder pickers via
showOpenDialog - Dynamic env variable rows (add/remove)
- Args parsed with quote-aware splitting
- Message passing protocol: save/cancel/browse* (webview→ext), setFilePath (ext→webview)
- Config selector:
$(gear) ConfigNameor$(add) Create Run Config - Run button:
$(play)(hidden when no active config) - Debug button:
$(bug)(hidden when no active config)
- User triggers Run/Debug
Runner.execute()validates config (name, script/module present)InterpreterResolver.resolve()finds Python interpreter:- Custom path → validate exists
- "selected" →
python.interpreterPathcommand → config fallback → PATH fallback
VariableResolver.resolve()expands${workspaceFolder},${file},${env:*}etc.- Build
vscode.DebugConfigurationwith typedebugpy, requestlaunch - Call
vscode.debug.startDebugging(folder, config, { noDebug: mode === 'run' })
Supported: ${workspaceFolder}, ${workspaceFolderBasename}, ${file}, ${fileBasename}, ${fileBasenameNoExtension}, ${fileDirname}, ${fileExtname}, ${relativeFile}, ${env:VARNAME}
npm run compile- Type-check + esbuild bundlenpm run watch- Development watch mode- Output:
dist/extension.js(42KB bundled) - F5 launches Extension Development Host
package.json- Extension manifest with full contributes sectiontsconfig.json- TypeScript strict mode, ES2021 targetesbuild.js- Standard VS Code esbuild pattern.vscode/launch.json- Extension host debug config.vscode/tasks.json- Build tasks.vscodeignore- VSIX packaging exclusionsAGENTS.md- Agent rules for AI assistancemedia/icon.svg- Activity bar icon (play triangle)- All
src/files listed in architecture above