Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>DeskhopNew to Visual Studio Code? Get it now.
Deskhop

Deskhop

Lucas Freitas

|
11 installs
| (0) | Free
Manda janelas do VSCode entre virtual desktops do Windows 11 — 3 botões na barra de status: desktop novo, espalhar, juntar.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

vscode-to-desktop · Deskhop

Marketplace Installs CI License: MIT Windows 11

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.7.2) — provado ponta-a-ponta no Windows 11 25H2 (build 26200). Publicado como extensão do VSCode (lucasftas.deskhop).


Extensão Deskhop (jeito mais fácil — botões nativos)

Além do script, o projeto é publicado como a extensão Deskhop no marketplace: instala e já traz os 3 botões na barra de status (Desktop novo · Espalhar · Juntar), sem precisar configurar nada.

code --install-extension lucasftas.deskhop

O clique é silencioso: nada de painel abrindo. A extensão roda o vscode-desktops.ps1 (embutido no pacote) por child_process com a janela do console escondida, mostrando só um aviso discreto na barra de status enquanto executa — erro, e só erro, vira notificação com "Ver log". O -Foreground continua funcionando porque nada rouba o foco.

📋 Toda execução vai pro log. Silencioso não quer dizer sem rastro: o canal Deskhop no painel de Saída registra horário, linha de comando, saída do script e exit code de cada clique — inclusive dos que deram certo. Abre pela paleta em Deskhop: Ver log. Falha parcial (uma janela que não moveu) faz o script sair com exit code ≠ 0, então ela vira notificação em vez de sumir.

Setting Padrão O que faz
deskhop.maximizeOnSpread true Ao Espalhar, cada janela chega em tela cheia no monitor principal. Desligue pra manter o tamanho/monitor de cada uma (spread -NoMaximize).
deskhop.closeDesktopsOnGather true Ao Juntar, fecha os virtual desktops. Desligue pra só trazer as janelas do VSCode, mantendo os desktops (gather -KeepDesktops).
deskhop.gatherUnifiesEverything true O Juntar traz também as janelas de outros programas e some com todos os desktops — fica um só. Desligue pra mexer apenas no VSCode, preservando desktop que tem outro programa (gather -VscodeOnly).
deskhop.showTerminal false Mostra o comando rodando no terminal integrado (abre o painel de baixo). Só pra depurar.
deskhop.powershellPath "" Caminho do PowerShell. Vazio = tenta o pwsh (PowerShell 7) e, se não existir, o powershell.exe que já vem no Windows. Preencha só se o seu estiver fora do PATH.

Como é uma extensão do marketplace, o Settings Sync a replica em todas as máquinas logadas na sua conta. Só Windows 11 (fora disso os botões não aparecem). Detalhe da extensão em docs/BOTAO-STATUSBAR.md.


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 e sobra um desktop só

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, e sem perguntar nada — a extensão roda o script escondido, então um prompt travaria o clique). Se a instalação automática falhar, o erro diz o comando exato pra rodar uma vez num terminal visível:

Install-Module VirtualDesktop -Scope CurrentUser

⚠️ O módulo é instalado por interpretador: tê-lo no PowerShell 7 não o coloca no powershell.exe 5.1, e vice-versa. Se a extensão cair no fallback (máquina sem PowerShell 7), pode ser preciso instalar de novo, lá.

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)
# Cada janela já chega em tela cheia (maximizada) no monitor PRINCIPAL do Windows
pwsh -File scripts\vscode-desktops.ps1 spread

# Espalhar mantendo o tamanho/monitor de cada janela
pwsh -File scripts\vscode-desktops.ps1 spread -NoMaximize

# Juntar todas de volta no desktop atual E fechar os desktops de onde elas saíram
pwsh -File scripts\vscode-desktops.ps1 gather

# Ver o que aconteceria, sem mover nem fechar nada
pwsh -File scripts\vscode-desktops.ps1 spread -DryRun
pwsh -File scripts\vscode-desktops.ps1 gather -DryRun

# 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) · -FollowWindow (send/move segue a janela) · -NoMaximize (spread não maximiza) · -Maximize (send/move maximiza no monitor principal) · -KeepDesktops (gather não fecha desktop) · -VscodeOnly (gather fecha só os desktops de onde saiu VSCode) · -DryRun (spread/gather só mostram o que fariam). move é alias de send. Passar o switch de um verbo pra outro (spread -VscodeOnly) erra na cara em vez de ser ignorado em silêncio.

🪟 O spread espalha TODAS as janelas do VSCode — inclusive a que está sem pasta aberta (aparece como Visual Studio Code) e as isoladas. Cada uma ganha o desktop dela; nenhuma fica empilhada em cima de outra. Quando duas janelas rendem o mesmo nome (duas sem pasta, ou o mesmo workspace aberto duas vezes), a segunda vira nome (2), a terceira nome (3). O spread não fecha desktop vazio — quem consolida é o gather.

🧹 O gather unifica: sobra um desktop só. Ele traz pro desktop atual todas as janelas — as do VSCode e as dos outros programas — e fecha os demais virtual desktops. Nenhuma janela é fechada: fechar um virtual desktop no Windows apenas realoca as janelas dele (testado), e o gather ainda move tudo explicitamente antes, pra o destino ser o seu desktop e não depender da ordem de remoção. Isso resolve o caso chato do desktop que parece vazio mas tem uma janela minimizada dentro. Use -DryRun pra ver a decisão antes, -VscodeOnly pra mexer só no VSCode (preservando desktop de outros programas) e -KeepDesktops pra só juntar as janelas.

🖥️ Tela cheia no monitor principal: o spread maximiza cada janela no monitor principal do Windows (o que tem a origem 0,0) depois de mandá-la pro desktop dela — assim cada desktop novo já abre com a janela cheia, em vez de herdar o tamanho/monitor de antes. Feito via SetWindowPlacement (não ativa nem rouba o foco, e funciona com a janela já em outro virtual desktop). Desliga com -NoMaximize.

⚠️ 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)
├── CHANGELOG.md              # histórico de versões (Keep a Changelog)
├── CONTRIBUTING.md           # como rodar, testar e as armadilhas do projeto
├── SECURITY.md               # como reportar falha + superfície de risco
├── CODE_OF_CONDUCT.md        # Contributor Covenant 2.1
├── LICENSE                   # MIT
├── CLAUDE.md                 # regras do projeto pra o Claude Code
├── .github/
│   ├── workflows/            # CI (lint + build + testes + VSIX) e Release por tag
│   ├── ISSUE_TEMPLATE/       # bug / ideia
│   └── PULL_REQUEST_TEMPLATE.md
├── assets/
│   └── icon.png              # ícone da extensão (128×128)
├── docs/
│   ├── PESQUISA.md           # pesquisa profunda + verificação adversarial (o "porquê" técnico)
│   ├── AUDITORIA-RISCOS.md   # levantamento do que pode quebrar (e o que a verificação derrubou)
│   ├── CHECKLIST-MANUAL.md   # cenários que nenhum teste automatizado cobre
│   ├── BOTAO-STATUSBAR.md    # botão na barra de status via Action Buttons (alternativa)
│   └── 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
├── src/
│   ├── extension.ts          # extensão: registra comandos e botões da barra de status
│   └── verbs.ts              # lógica pura (botões + verbo/linha de comando), testável sem VSCode
└── tests/
    ├── verbs.test.mjs           # testes da extensão (node --test)
    └── vscode-desktops.Tests.ps1 # testes do script (Pester 5) — não movem janela

Os arquivos IMPLEMENTATIONS.md, OPERATIONS.md e SESSIONS.md na raiz são o registro interno de sessões e operações.

Desenvolvimento

npm install
npm run compile     # tsc
npm run lint        # eslint
npm test            # compile + testes da extensão + testes Pester do script
npm run package     # gera dist/deskhop-<versão>.vsix

F5 no VSCode abre uma janela de desenvolvimento com a extensão carregada.

O CI (.github/workflows/ci.yml) roda em windows-latest porque a ferramenta é Windows-only. Movimento de janela não é coberto por teste automatizado de propósito — mexeria na tela de quem roda; a validação é manual, com janela descartável (ver CONTRIBUTING.md).

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.
  • O alternador de desktops do shell pode crashar sob rajada de operações (classe MScholtes/VirtualDesktop#106 — aconteceu de verdade num spread: access violation em Switcher.dll, o explorer.exe reinicia e a conexão COM do processo morre). Desde a 0.8.0 o script re-tenta o engasgo transiente com backoff, espaça as operações e, se o explorer reiniciou, sinaliza exit 3 — a extensão repete a operação uma vez num processo novo, que completa o que faltou (desktops e janelas já movidas sobrevivem ao restart).
  • ⛔ 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).

Releases

Versão atual: v0.8.0. Todas as releases (com o .vsix anexado) em:

https://github.com/lucasftas/vscode-to-desktop/releases

Licença

MIT © Lucas Freitas.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft