---
title: 'Windows'
description: 'Run the Stackbone CLI on Windows from WSL2 or Git Bash, and fix a tunnel that Windows will not let start.'
position: 9
---
# Windows
> The CLI runs on Windows from **WSL2** or **Git Bash**. WSL2 is the path we
> recommend, because the CLI behaves there exactly as it does on Linux.
> PowerShell and CMD stop the CLI at startup with a message that sends you to
> one of the two.
## Pick a shell
| Shell | Works | What to know |
| -------------- | ----- | ------------------------------------------------------------------------------------------------ |
| WSL2 (Ubuntu) | Yes | Same behaviour as Linux. Smart App Control and AppLocker do not check the Linux binaries it runs |
| Git Bash | Yes | The CLI downloads the Windows build of `frpc`, which Windows can block. See below |
| PowerShell/CMD | No | The CLI exits with `unsupported_platform` |
Both working shells need Docker. With WSL2, Docker Desktop works as long as
its WSL2 integration is on for your Ubuntu distribution.
## Set up WSL2
1. Install Ubuntu from PowerShell, then reboot:
```sh
wsl --install -d Ubuntu
```
2. Open the Ubuntu terminal and install Node 24 and pnpm there. The Node you
installed on Windows is a different install, so do not call it from WSL2.
3. Install the CLI inside Ubuntu and sign in:
```sh
pnpm add -g @stackbone/cli
stackbone login
```
4. Keep your workspace on the Linux file system (for example
`~/code/my-agent`), not under `/mnt/c/`. File watching across the two file
systems is slow and misses changes.
## Use Git Bash
Git Bash works for every command. Two things behave differently from Linux.
**Ctrl-C.** Git Bash terminals do not always give the CLI a real
pseudo-terminal, so the CLI re-runs itself under `winpty` for `stackbone dev`.
If `winpty` is not on your `PATH`, run `winpty stackbone dev`. See
[Ctrl-C does not stop `stackbone dev` in Git Bash](/docs/cli/guides/troubleshooting#ctrl-c-does-not-stop-stackbone-dev-in-git-bash).
**The tunnel binary.** `stackbone dev` always opens a tunnel, and it uses
`frpc` for that. The first run downloads the Windows `frpc.exe` into
`~/.cache/stackbone/bin/` and extracts it with PowerShell. Windows may refuse
to run that file. The next section covers what to do.
## If Windows blocks frpc
**Symptom:** `stackbone dev` stops at the tunnel stage with
`The OS refused to run frpc` (`error.code` is `permission`). Running
`frpc.exe` by hand gives `Permission denied`, and Defender's protection history
shows nothing.
**Cause:** Windows is blocking an unsigned executable. It is not the file
mode and not your `PATH`. The usual reasons:
| Blocker | Where it logs |
| ------------------ | ----------------------------------------------- |
| Mark of the Web | Nowhere. A browser tags every file it downloads |
| Smart App Control | Event Viewer, under CodeIntegrity |
| Microsoft Defender | Protection history, often as a HackTool |
| AppLocker or WDAC | Your IT department's policy logs |
**Fix:** try these in order. The error message prints the full path to the
binary, so use that path in the commands.
1. If you downloaded `frpc` with a browser, remove the download tag in PowerShell:
```powershell
Unblock-File "$HOME\.cache\stackbone\bin\frpc-.exe"
```
2. Add an exclusion for the folder in Windows Security, under
**Virus & threat protection** > **Manage settings** > **Exclusions**.
3. Check **App & browser control** > **Smart App Control**. Turning it off
lets the binary run, but Windows may not let you turn it back on without a
reinstall. Decide that one for yourself.
4. On a laptop your company manages, you usually cannot change any of these.
Use WSL2 instead.
`frpc` versions are not interchangeable. The CLI pins the version that matches
the Stackbone relay, and it only looks for that version in the cache. If you
download `frpc` by hand, take the version the error message names, or point
`STACKBONE_FRPC_BIN` at your binary. See
[Using a system `frpc` binary](/docs/cli/guides/local-development#using-a-system-frpc-binary).
## What's next
- [Getting started](/docs/cli/guides/getting-started): from zero to a running agent.
- [Local development](/docs/cli/guides/local-development): what `stackbone dev` does at each stage.
- [Troubleshooting](/docs/cli/guides/troubleshooting): the other failures, keyed on `error.code`.