vscode-to-desktop
Manda janelas do Visual Studio Code pra virtual desktops do Windows 11 por linguagem natural — cada projeto no seu próprio desktop, sem mouse e sem Task View.
Status: ✅ Funcional (v0.1.0) — provado ponta-a-ponta no Windows 11 25H2 (build 26200).
Proposta / Visão
Quem trabalha com vários workspaces do VSCode abertos ao mesmo tempo (um por projeto) acaba com todas as janelas empilhadas num desktop só. O Windows 11 tem virtual desktops (Win+Tab), mas:
- não tem atalho de teclado nativo pra mover uma janela já aberta pra outro desktop (só arrastando no Task View);
- e mesmo via script, enumerar as janelas do VSCode é traiçoeiro — todas pertencem a um único processo
Code.exe (Electron), então a abordagem óbvia (Get-Process Code) enxerga uma janela só.
Esta ferramenta resolve os dois: um script PowerShell que enumera todas as janelas do VSCode (via Win32 EnumWindows) e move cada uma pro virtual desktop que você quiser, criando/nomeando desktops na hora.
Problema que resolve
| Dor |
Antes |
Com a ferramenta |
| Mover janela aberta entre desktops |
Só arrastando no Task View (mouse) |
send, um comando |
| Organizar N projetos |
Um a um, na mão |
spread — cada projeto no seu desktop de uma vez |
| Achar as janelas do VSCode |
Get-Process vê só 1 |
EnumWindows pega todas |
| Voltar ao normal |
Fechar desktops um a um |
gather — junta tudo |
Usuário-alvo
Power-users com muitos workspaces do VSCode abertos que querem separar contexto visual por projeto — sem instalar tiling window manager nem trocar o fluxo de trabalho.
Escopo do MVP (v0.1.0)
- Listar desktops + em qual desktop está cada janela do VSCode (
list)
- Mover uma janela específica (por nome de workspace ou HWND) pra um desktop, criando-o se não existir (
send)
- Mover a janela em foco pra um desktop novo, seguindo a janela (
send sem alvo, ou -Foreground)
- Espalhar todas as janelas do VSCode, uma por desktop (
spread)
- Juntar tudo de volta no desktop atual (
gather)
- Criar/nomear desktop (
new)
Fora de escopo (v0.1.0)
- Persistência entre reboots (Windows devolve tudo pro Desktop 1 ao reiniciar)
- Vigia residente / atalho de teclado global / tiling WM (decisão de projeto: operar sob demanda, não residente)
- Outros apps além do VSCode (a lógica generaliza, mas o foco é
Code.exe)
Premissa crítica (se falsa, mata o MVP)
A COM interna IVirtualDesktopManagerInternal do shell é acessível no Windows 11 25H2 (26200) e permite criar desktop + mover janela de outro processo.
Status: CONFIRMADA (a API pública IVirtualDesktopManager NÃO faz isso — dá E_ACCESSDENIED). O 25H2 é enablement package sobre o 24H2 (26100): mesmos binários, mesmo IID de COM. Provado empírico na máquina de referência (bind + move + verify E2E). Ver docs/PESQUISA.md.
Stack e arquitetura
- PowerShell (Windows PowerShell 5.1 / PowerShell 7) — sem admin
- Módulo
VirtualDesktop (MScholtes, PSGallery) v1.5.11 — fala com a COM interna do shell, auto-detecta o build/IID
- Win32
EnumWindows via Add-Type (C# inline, compilado pelo csc nativo — não instala nada) — resolve o gotcha Electron
- Delegação por-tarefa a modelo Haiku (quando operado via Claude Code) — a demanda é trivial, roda barato
Como usar
O script auto-instala o módulo VirtualDesktop na 1ª execução (sem admin). Pra evitar o prompt de confiança do PSGallery, dá pra instalar antes (opcional): Install-Module VirtualDesktop -Scope CurrentUser.
Comandos (rodar sem PowerShell elevado):
# Ver desktops + onde está cada janela do VSCode
pwsh -File scripts\vscode-desktops.ps1 list
# Mandar o workspace "facialscale" pra um desktop novo chamado "Facial"
pwsh -File scripts\vscode-desktops.ps1 send -Match facialscale -To Facial
# Espalhar TODAS as janelas, cada uma no seu desktop (nomeado pelo workspace)
pwsh -File scripts\vscode-desktops.ps1 spread
# Juntar todas de volta no desktop atual
pwsh -File scripts\vscode-desktops.ps1 gather
# Só criar/nomear um desktop
pwsh -File scripts\vscode-desktops.ps1 new -To Comercial
# Mover a janela EM FOCO ("move essa janela"): cria desktop nomeado pelo workspace e segue.
# Rodar do terminal integrado DA PRÓPRIA janela VSCode que quer mover (ela fica em foco).
pwsh -File scripts\vscode-desktops.ps1 send -Foreground
Switches: -Hwnd <n> (mira por handle exato) · -To <idx|nome> (destino) · -IncludeWelcome (spread inclui a janela vazia) · -FollowWindow (send/move segue a janela). move é alias de send.
⚠️ Sobre -Foreground: pega a janela em foco no instante da execução (GetForegroundWindow). Funciona quando a janela-alvo está em foco. Disparado por automação sem foco ativo numa janela do VSCode, ele não move nada (falha segura) e pede -Match/-Hwnd.
Botão na barra de status (opcional — sem digitar comando)
Pra quem prefere clicar a digitar, dá pra ter os verbos como botões na barra de status do VSCode, via a extensão VsCode Action Buttons — sem escrever extensão própria.
O clique roda o comando no terminal integrado da própria janela → a janela do VSCode fica em foco, então o -Foreground funciona (mesmo motivo pelo qual o terminal integrado funciona e a automação desanexada não).
code --install-extension seunlanlege.action-buttons
Depois, no settings.json (global ou do workspace), 3 botões com ícones de linha nativos (codicons):
"actionButtons": {
"reloadButton": null,
"commands": [
{ "name": "$(empty-window) Desktop novo", "singleInstance": true, "focus": false,
"command": "pwsh -NoProfile -File 'CAMINHO/vscode-desktops.ps1' send -Foreground" },
{ "name": "$(multiple-windows) Espalhar", "singleInstance": true, "focus": false,
"command": "pwsh -NoProfile -File 'CAMINHO/vscode-desktops.ps1' spread" },
{ "name": "$(combine) Juntar", "singleInstance": true, "focus": false,
"command": "pwsh -NoProfile -File 'CAMINHO/vscode-desktops.ps1' gather" }
]
}
Ctrl+Shift+P → Refresh Action Buttons (ou reabre a janela) e os botões aparecem no canto inferior esquerdo. Receita completa e explicação em docs/BOTAO-STATUSBAR.md.
Estrutura de pastas
vscode-to-desktop/
├── README.md # este arquivo (estado funcional)
├── CLAUDE.md # regras do projeto pra o Claude Code
├── docs/
│ ├── PESQUISA.md # pesquisa profunda + verificação adversarial (o "porquê" técnico)
│ ├── BOTAO-STATUSBAR.md # botão na barra de status via Action Buttons (opcional)
│ └── specs/
│ ├── PRD.md # decisões técnicas + fontes + snippets
│ └── Spec.md # milestones (o que foi construído + critério de pronto)
└── scripts/
└── vscode-desktops.ps1 # a ferramenta
Riscos conhecidos
- IID da COM interna muda a cada feature update grande do Windows (22H2→23H2→24H2). O 25H2 está salvo (enablement do 24H2); a quebra virá num update que reescreva o shell. Mitigação:
Update-Module VirtualDesktop. Fallback sempre disponível: Task View nativo.
- ⛔ Não rodar elevado — um processo em high integrity não move janela de app medium (o shell roda medium) → falha silenciosa.
- Mover não quebra o VSCode (confirmado — bug
microsoft/vscode#146915: funciona normal após mover; o único problema é não lembrar a posição após restart).
Licença
A definir (candidato: MIT — repo de comunidade).