# How Tabby Integrates with WSL and Git-Bash on Windows: ShellProvider Architecture Explained

> Learn how Tabby integrates with WSL and Git-Bash on Windows. Discover the ShellProvider architecture that queries the registry to launch your terminals.

- Repository: [Eugene/tabby](https://github.com/Eugeny/tabby)
- Tags: architecture
- Published: 2026-03-03

---

**Tabby discovers and launches WSL and Git-Bash terminals on Windows through Angular-registered ShellProvider classes that query the Windows registry and return fully-configured Shell objects to the terminal UI.**

Tabby, the open-source terminal emulator by Eugeny, integrates seamlessly with Windows Subsystem for Linux (WSL) and Git-Bash through a pluggable provider architecture. This deep integration allows the application to automatically detect installed distributions and shell environments without manual path configuration. Understanding how Tabby handles WSL and Git-Bash integration on Windows reveals the sophisticated registry inspection and platform detection mechanisms that power modern terminal emulation.

## ShellProvider Architecture and Platform Detection

Tabby's shell discovery relies on the **ShellProvider** abstract class implemented in the `tabby-electron` package. At application startup, Angular's dependency injection system registers two critical providers in [`tabby-electron/src/index.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-electron/src/index.ts): `WSLShellProvider` extending `ShellProvider`, and `GitBashShellProvider` extending `WindowsBaseShellProvider`.

Both providers implement an asynchronous `provide()` method that first validates the host platform:

```typescript
if (this.hostApp.platform !== Platform.Windows) {
    return []
}

```

This guard clause prevents WSL and Git-Bash entries from appearing on macOS or Linux systems, ensuring platform-appropriate shell options. The providers return empty arrays on non-Windows platforms, effectively excluding these shells from the available profiles list.

## WSL Integration via Registry Inspection

### Distribution Discovery

The `WSLShellProvider` class in [`tabby-electron/src/shells/wsl.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-electron/src/shells/wsl.ts) queries the Windows registry key `Software\Microsoft\Windows\CurrentVersion\Lxss` using the **windows-native-registry** library. This key contains sub-entries for each installed WSL distribution, allowing Tabby to enumerate available environments dynamically.

When a default distribution is configured, Tabby creates a shell entry that executes `wsl.exe` with environment variables including `TERM=xterm-color` and `COLORTERM=truecolor` for proper color support.

### Executable Fallback Logic

For compatibility with older Windows builds, Tabby checks the `WIN_BUILD_WSL_EXE_DISTRO_FLAG` constant. If the system lacks support for the `wsl.exe` distribution flag, the provider falls back to `%windir%\system32\bash.exe`. This ensures functionality across Windows 10 versions that predate modern WSL executable parameters.

### Version Differentiation

The provider inspects each distribution's registry entries to determine whether it runs WSL 1 or WSL 2. It constructs distinct `Shell` objects for each distribution, assigning appropriate icons from an internal map that matches distribution names like "Ubuntu-22.04" or "Debian".

## Git-Bash Integration Mechanism

### Installation Path Resolution

The `GitBashShellProvider` in [`tabby-electron/src/shells/gitBash.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-electron/src/shells/gitBash.ts) locates the Git for Windows installation by reading the `Software\GitForWindows` key under both **HKLM** (HKEY_LOCAL_MACHINE) and **HKCU** (HKEY_CURRENT_USER) registry hives. The `InstallPath` value provides the base directory for constructing the executable path.

### Shell Configuration

Upon finding the installation, Tabby builds a `Shell` entry executing `<InstallPath>\bin\bash.exe` with the arguments `--login -i` to ensure proper interactive shell initialization. The environment variables are populated through the inherited `WindowsBaseShellProvider.getEnvironment()` method, which injects standard Windows variables including `PATH` and `HOME`.

## Shell Object Structure and UI Binding

Both providers return **Shell** objects defined in the `tabby-local` package. Each object contains:

- `id`: Stable identifier (`'wsl'` or `'git-bash'`)
- `name`: UI label (e.g., "WSL / Ubuntu-22.04" or "Git Bash")
- `command`: Absolute executable path
- `args`: Command-line arguments array
- `icon`: SVG icon loaded via `require('../icons/...')`
- `env`: Environment variables for terminal rendering

These objects merge with other shell providers (PowerShell, CMD) and populate the **Terminal Settings** UI. The [`tabby-terminal/src/components/terminalSettingsTab.component.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-terminal/src/components/terminalSettingsTab.component.ts) file handles the presentation logic, including a WSL-specific warning about the Volume Mixer for managing terminal bell sounds, defined in the companion `.pug` template.

## Practical Configuration Examples

### Listing Available Shells Programmatically

You can inspect discovered shells using the ShellService:

```typescript
import { Injectable } from '@angular/core';
import { ShellService } from 'tabby-core';

@Injectable({ providedIn: 'root' })
export class ShellInspector {
  constructor(private shells: ShellService) {}

  async logAvailableShells() {
    const list = await this.shells.provideShells();
    for (const s of list) {
      console.log(`- ${s.name} (id: ${s.id})`);
    }
  }
}

```

### Setting a Default WSL Profile

Configure your preferred distribution in Tabby's config file:

```json
{
  "terminal": {
    "profile": "WSL / Ubuntu-22.04"
  }
}

```

### Extending with Custom Providers

To add unsupported WSL distributions, extend the base provider:

```typescript
import { ShellProvider, Shell } from 'tabby-local';
import { Injectable } from '@angular/core';
import { HostAppService, Platform } from 'tabby-core';

@Injectable()
export class CustomWslProvider extends ShellProvider {
  constructor(private hostApp: HostAppService) { super(); }

  async provide(): Promise<Shell[]> {
    if (this.hostApp.platform !== Platform.Windows) return [];
    return [{
      id: 'custom-wsl',
      name: 'WSL / MyCustomDistro',
      command: 'C:\\Windows\\System32\\wsl.exe',
      args: ['-d', 'MyCustomDistro'],
      env: { TERM: 'xterm-256color', COLORTERM: 'truecolor' },
      icon: require('../icons/linux.svg')
    }];
  }
}

```

Register this class in [`tabby-electron/src/index.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-electron/src/index.ts) to expose the new entry in the UI.

## Summary

- Tabby uses **WSLShellProvider** and **GitBashShellProvider** classes registered in [`tabby-electron/src/index.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-electron/src/index.ts) to detect Windows shells.
- **Registry inspection** of `Software\Microsoft\Windows\CurrentVersion\Lxss` enables automatic WSL distribution discovery, while Git-Bash detection queries `Software\GitForWindows`.
- **Build-specific logic** determines whether to use `wsl.exe` or fall back to `bash.exe` based on `WIN_BUILD_WSL_EXE_DISTRO_FLAG`.
- **Shell objects** encapsulate executable paths, arguments, and environment variables for seamless UI integration in [`terminalSettingsTab.component.ts`](https://github.com/Eugeny/tabby/blob/main/terminalSettingsTab.component.ts).
- The **WindowsBaseShellProvider** supplies common environment handling shared across Windows shell implementations.

## Frequently Asked Questions

### How does Tabby detect available WSL distributions without manual configuration?

Tabby queries the Windows registry key `Software\Microsoft\Windows\CurrentVersion\Lxss` using the windows-native-registry library. This key contains entries for every installed distribution, including their names and default status. The provider parses these entries in [`tabby-electron/src/shells/wsl.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-electron/src/shells/wsl.ts) to generate shell profiles automatically.

### Why does Tabby show different executables for WSL on older Windows versions?

The `WSLShellProvider` checks for `WIN_BUILD_WSL_EXE_DISTRO_FLAG` to determine if the system supports modern `wsl.exe` distribution flags. On older Windows 10 builds lacking this support, Tabby falls back to `%windir%\system32\bash.exe` to ensure compatibility while maintaining the same user experience.

### Can I use Tabby's Git-Bash integration if I installed Git for Windows in a custom location?

Yes. The `GitBashShellProvider` searches both HKLM and HKCU registry hives for `Software\GitForWindows`. As long as the installation properly registered its path in the Windows registry, Tabby will locate `bin\bash.exe` automatically regardless of the installation directory.

### Where does Tabby store the configuration for default shell profiles?

Default profiles are stored in Tabby's configuration file (typically `~/.config/tabby/config.json` on Windows systems). Set the `terminal.profile` value to match the `name` property of the desired shell returned by the provider, such as "WSL / Ubuntu-22.04" or "Git Bash".