diff --git a/tabby-local/src/icons/vs.svg b/tabby-local/src/icons/vs.svg
new file mode 100644
index 00000000..e7ae716d
--- /dev/null
+++ b/tabby-local/src/icons/vs.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tabby-local/src/index.ts b/tabby-local/src/index.ts
index 92fd7d7f..7c208f24 100644
--- a/tabby-local/src/index.ts
+++ b/tabby-local/src/index.ts
@@ -38,6 +38,7 @@ import { PowerShellCoreShellProvider } from './shells/powershellCore'
import { WindowsDefaultShellProvider } from './shells/winDefault'
import { WindowsStockShellsProvider } from './shells/windowsStock'
import { WSLShellProvider } from './shells/wsl'
+import { VSDevToolsProvider } from './shells/vs'
import { AutoOpenTabCLIHandler, OpenPathCLIHandler, TerminalCLIHandler } from './cli'
import { LocalProfilesService } from './profiles'
@@ -73,6 +74,7 @@ import { LocalProfilesService } from './profiles'
{ provide: ShellProvider, useClass: GitBashShellProvider, multi: true },
{ provide: ShellProvider, useClass: POSIXShellsProvider, multi: true },
{ provide: ShellProvider, useClass: WSLShellProvider, multi: true },
+ { provide: ShellProvider, useClass: VSDevToolsProvider, multi: true },
{ provide: ProfileProvider, useClass: LocalProfilesService, multi: true },
diff --git a/tabby-local/src/shells/vs.ts b/tabby-local/src/shells/vs.ts
new file mode 100644
index 00000000..78f3b874
--- /dev/null
+++ b/tabby-local/src/shells/vs.ts
@@ -0,0 +1,68 @@
+import * as path from 'path'
+import * as fs from 'fs/promises'
+import { Injectable } from '@angular/core'
+import { HostAppService, Platform } from 'tabby-core'
+
+import { ShellProvider, Shell } from '../api'
+
+/** @hidden */
+@Injectable()
+export class VSDevToolsProvider extends ShellProvider {
+ constructor (
+ private hostApp: HostAppService,
+ ) {
+ super()
+ }
+
+ async provide (): Promise {
+ if (this.hostApp.platform !== Platform.Windows) {
+ return []
+ }
+
+ const parentPath = path.join(process.env['programfiles(x86)'] ?? 'C:\\Program Files (x86', 'Microsoft Visual Studio')
+
+ try {
+ await fs.stat(parentPath)
+ } catch {
+ return []
+ }
+
+ const result: Shell[] = []
+ for (const version of await fs.readdir(parentPath)) {
+ const bat = path.join(parentPath, version, 'Community\\Common7\\Tools\\VsDevCmd.bat')
+ try {
+ await fs.stat(bat)
+ } catch {
+ continue
+ }
+ result.push({
+ id: `vs-cmd-${version}`,
+ name: `Developer Prompt for VS ${version}`,
+ command: 'cmd.exe',
+ args: ['/k', bat],
+ icon: require('../icons/vs.svg'),
+ env: {},
+ })
+ }
+ return result
+
+ // return [
+ // {
+ // id: 'cmderps',
+ // name: 'Cmder PowerShell',
+ // command: 'powershell.exe',
+ // args: [
+ // '-ExecutionPolicy',
+ // 'Bypass',
+ // '-nologo',
+ // '-noprofile',
+ // '-noexit',
+ // '-command',
+ // `Invoke-Expression '. ''${path.join(process.env.CMDER_ROOT, 'vendor', 'profile.ps1')}'''`,
+ // ],
+ // icon: require('../icons/cmder-powershell.svg'),
+ // env: {},
+ // },
+ // ]
+ }
+}