skip to content

cls — Clear Console Screen

Clear all text from the cmd.exe or PowerShell console window and reset the cursor to the top-left — the single command for resetting a terminal session's visible output.

15 min read 54 snippets deep dive

cls — Clear Console Screen#

What it is#

cls (Clear Screen) is a built-in Windows command that erases all text currently visible in the console window and moves the cursor to the top-left corner — equivalent to the Unix clear command. Use it at the top of interactive batch menus, after long command output, or anywhere you want a clean terminal view. In PowerShell, Clear-Host (alias cls) does the same thing.

Availability#

cls is an internal cmd.exe command present on every Windows version, not a standalone .exe. It also works as an alias in PowerShell via Clear-Host.

help cls

Output:

Clears the screen.

CLS

Syntax#

cls takes no arguments.

cls

Output: (screen cleared — cursor moves to top-left)

Clearing the screen in a batch script#

Batch menus and interactive scripts often call cls before displaying a menu so previous output doesn’t clutter the view.

@echo off
:menu
cls
echo ==================
echo   Maintenance Menu
echo ==================
echo  1. Backup files
echo  2. Clean temp
echo  3. Exit
echo ==================
set /P choice=Choose: 
if "%choice%"=="1" goto backup
if "%choice%"=="2" goto clean
if "%choice%"=="3" exit /b
goto menu

Output:

==================
  Maintenance Menu
==================
 1. Backup files
 2. Clean temp
 3. Exit
==================
Choose:

Clearing after a long-running command#

Calling cls after verbose output from a build tool or installer leaves a clean terminal for subsequent commands.

@echo off
echo Running installer...
msiexec /quiet /i myapp.msi
cls
echo Installation complete.

Output:

Installation complete.

Suppressing cls output in scripts#

cls itself produces no stdout; it writes directly to the console buffer. Redirecting it to NUL is a no-op but harmless — it does not suppress the screen-clear effect.

cls > NUL
echo Screen cleared.

Output:

Screen cleared.

cls in PowerShell#

In PowerShell, cls is an alias for Clear-Host. Both clear the screen identically; Clear-Host is the preferred explicit form in scripts.

cls

Output: (screen cleared)

Clear-Host

Output: (screen cleared)

Common pitfalls#

  1. cls clears only the visible buffer, not scroll-back history — the console’s scroll-back buffer is cleared as well, so prior output is unrecoverable from the window; pipe important output to a file before calling cls.
  2. cls inside a pipe is a no-opecho text | cls does not make sense; cls ignores stdin and writes directly to the console.
  3. Redirecting cls to a file creates an empty filecls > screen.txt creates an empty file; the escape sequences go to the console handle, not stdout.
  4. Does not work in non-interactive contexts — when cmd.exe is spawned without a console (e.g. via CreateProcess with DETACHED_PROCESS), cls may fail silently.

Real-world recipes#

Interactive loop with periodic clear#

@echo off
:loop
cls
echo Current time: %TIME%
echo Press Ctrl+C to exit, any key to refresh.
pause > NUL
goto loop

Output:

Current time: 14:22:05.34
Press Ctrl+C to exit, any key to refresh.

Clear screen at the start of a deployment script#

@echo off
cls
echo ===================================
echo  Deploy: MyApp v2.1.0
echo  Host:   myhost
echo  Date:   %DATE%
echo ===================================
echo.

Output:

===================================
 Deploy: MyApp v2.1.0
 Host:   myhost
 Date:   Mon 04/28/2026
===================================

How cls actually clears the screen#

cls is not a separate executable on Windows — it is an internal command implemented inside cmd.exe. When you type cls, the shell calls the Win32 console APIs (GetConsoleScreenBufferInfo, FillConsoleOutputCharacter, FillConsoleOutputAttribute, SetConsoleCursorPosition) to overwrite every cell in the visible window with spaces, reset the attributes to the current default colour, and move the cursor home. There is no escape sequence being emitted to stdout — the call is direct against the console handle. This matters because it explains why redirecting cls is a no-op: the action happens through a side-channel that > and | cannot capture.

rem Demonstrates that cls writes nothing to stdout
cls > saved.txt
dir saved.txt

Output:

03/24/2026  10:14 AM                 0 saved.txt

The file is zero bytes — the screen was cleared but nothing reached the redirected handle.

ANSI escape sequences as a portable alternative#

Modern Windows 10 (1607+) and Windows 11 consoles understand the same VT100/ANSI escape sequences as Linux and macOS terminals. Emitting ESC[2J clears the screen and ESC[H (or ESC[0;0H) homes the cursor — together they are the portable cross-platform equivalent of cls. The escape byte is 0x1B (decimal 27). In a batch script you can produce it with prompt $E trick or by embedding the literal byte in a here-doc with forfiles, but PowerShell and modern shells let you write it directly.

# PowerShell — write the ANSI clear sequence directly
$esc = [char]27
Write-Host "$esc[2J$esc[H" -NoNewline

Output: (screen cleared the same as cls)

# PowerShell 6+ accepts `e for the escape byte
Write-Host "`e[2J`e[H" -NoNewline

Output: (screen cleared)

For mixed scripts that may run in older shells, Clear-Host remains the safe path. ANSI sequences fail silently on legacy conhost.exe builds prior to Windows 10 1607, printing literal ←[2J characters instead of clearing.

VT100 sequences cheat sheet#

The same byte stream that clears the screen can also scroll, colour, and reposition the cursor. These are useful when writing TUIs, progress meters, or animations directly from cmd.exe or PowerShell without a library.

SequenceEffect
ESC[2JErase entire screen (cursor stays put)
ESC[3JErase entire screen and scroll-back buffer (Windows 10 1809+)
ESC[HCursor to row 1, column 1
ESC[0;0HSame as above, explicit row/column
ESC[KErase from cursor to end of line
ESC[1KErase from start of line to cursor
ESC[2KErase the entire current line
ESC[<n>AMove cursor up n rows
ESC[<n>BMove cursor down n rows
ESC[<n>CMove cursor right n columns
ESC[<n>DMove cursor left n columns
ESC[sSave cursor position
ESC[uRestore saved position
ESC[?1049hSwitch to alternate screen buffer (vim-style)
ESC[?1049lSwitch back to main buffer
# Full scroll-back clear — equivalent to Windows Terminal Ctrl+Shift+K
Write-Host "`e[2J`e[3J`e[H" -NoNewline

Output: (screen and scroll-back history cleared)

Clearing the scroll-back buffer#

By default, cls only blanks the visible viewport; lines that scrolled off the top remain in the scroll-back buffer and can be retrieved with the mouse wheel. On Windows 10 1809 and later the ESC[3J sequence wipes the scroll-back as well, matching what clear does on Linux when called with -x or what Windows Terminal does on Ctrl+Shift+K.

function Clear-AllBuffers {
    Write-Host "`e[2J`e[3J`e[H" -NoNewline
}
Clear-AllBuffers

Output: (visible window and scroll-back history both gone)

In legacy conhost.exe and Windows Terminal you can also clear the scroll-back via the right-click menu (Properties → Layout lets you shrink the buffer to zero rows, although that has side effects). For pure cmd.exe without VT support, the only true scroll-back wipe is closing and reopening the console.

cls vs clear — cross-platform comparison#

cls is the Windows internal; clear is the POSIX equivalent shipped on Linux, macOS, BSD, and inside WSL distributions. The two cannot be used interchangeably without aliasing — clear on cmd.exe reports “is not recognised as an internal or external command” and cls in a Bash shell produces a similar error. PowerShell normalises both: cls and clear are both aliases of Clear-Host.

ShellCommandImplementation
cmd.execlsInternal — Win32 console API
PowerShell 5.1Clear-Host (cls, clear)Function calling Win32 console API
PowerShell 7 (Windows)Clear-Host (cls, clear)Emits ESC[2J ESC[3J ESC[H
PowerShell 7 (Linux/macOS)Clear-Host (cls, clear)Shells out to clear
Bash / Zsh / FishclearReads clear capability from terminfo
WSLclearSame as Bash — uses terminfo
Windows Terminal (any shell)Built-in: Ctrl+L / Ctrl+Shift+KRenderer API call
# Linux / WSL — clear uses terminfo
clear              # equivalent of cls
clear -x           # clear visible but keep scroll-back (Linux only)
tput clear         # raw terminfo capability
printf '\e[2J\e[H' # raw ANSI — portable everywhere modern

Output: (screen cleared)

Keyboard shortcut equivalents#

You rarely need to type cls at an interactive prompt — every modern Windows terminal has a keyboard shortcut that does the same thing. Knowing these saves four keystrokes hundreds of times a day.

ShortcutWhere it worksWhat it does
Ctrl+LPowerShell 5.1+ (PSReadLine), bash, zsh, fish, Windows TerminalClears visible viewport, keeps scroll-back
Ctrl+Shift+KWindows Terminal (all profiles)Clears the entire buffer (visible + scroll-back)
Cmd+KiTerm2, Apple TerminalClears scroll-back too
Right-click → Clear BufferWindows Terminal title bar menuSame as Ctrl+Shift+K
cls / clearcmd / PowerShell / bashVisible viewport only (Windows)

Ctrl+L in PowerShell only works when the PSReadLine module is loaded — that is the default in PowerShell 5.1+ and 7+. Inside a cmd.exe window, Ctrl+L does nothing; you must type cls.

Windows Terminal vs conhost behaviour#

Windows ships two console hosts. conhost.exe is the legacy host used when you launch cmd.exe directly from Win+R. Windows Terminal (wt.exe) is the modern tabbed host installed by default on Windows 11 and via the Store on Windows 10. They differ in how they handle clear operations.

Featureconhost.exeWindows Terminal
cls behaviourClears visible viewportClears visible viewport
ESC[2J supportYes (Windows 10 1607+)Yes
ESC[3J (scroll-back wipe)Windows 10 1809+Yes
Scroll-back retained after clsYes (mouse wheel up)Yes
Alternate screen bufferLimitedFull
Keyboard Ctrl+LNoYes (in PSReadLine shells)
Ctrl+Shift+KNoYes (clears all)
RendererGDIDirectWrite (GPU)

If a script needs to reset everything including scroll-back regardless of which host the user is on, write both cls and the ESC[3J sequence — conhost ignores ESC[3J on builds older than 1809 but does no harm.

cls in PowerShell — Clear-Host in depth#

Clear-Host is an advanced PowerShell function (not a cmdlet) built into the engine. Inspecting its definition shows it as a thin wrapper that uses platform-specific logic.

Get-Command Clear-Host | Format-List *

Output:

CommandType        : Function
Name               : Clear-Host
Definition         : ...uses [Console]::Clear() on Windows...
Module             :
...
# Inspect the function body
(Get-Command Clear-Host).ScriptBlock

Output:

$RawUI = $Host.UI.RawUI
$RawUI.CursorPosition = @{X=0;Y=0}
$RawUI.SetBufferContents(
    @{Top = -1; Bottom = -1; Right = -1; Left = -1},
    @{Character=' '; ForegroundColor=$rawui.ForegroundColor; BackgroundColor=$rawui.BackgroundColor}
)

PowerShell calls into the host’s RawUI and resets the entire buffer to space characters with current colours. On non-Windows PowerShell (Linux/macOS) the engine substitutes a call to the system clear binary instead.

# All three forms are identical
cls
clear
Clear-Host

Output: (screen cleared three times)

Programmatic clear from .NET#

If a script is mixing PowerShell with raw .NET, System.Console.Clear() does the same thing as cls. This is the call PowerShell itself makes under the hood on Windows.

[System.Console]::Clear()

Output: (screen cleared)

A C# or PowerShell automation that does not have a real console (e.g. a service or a redirected process) will throw System.IO.IOException: The handle is invalid — check [System.Console]::IsOutputRedirected first.

if (-not [Console]::IsOutputRedirected) {
    [Console]::Clear()
} else {
    Write-Host "(clear skipped — no console attached)"
}

Output: (screen cleared, or “no console attached”)

Clearing inside the Win32 API#

Outside of cls, the canonical Win32 sequence is exactly what cmd.exe does internally: query the buffer, write spaces over every cell, write attributes over every cell, then home the cursor. Knowing this helps when writing native console tools or debugging why a PowerShell host like ConEmu or Cmder leaves stale colours after a clear.

// Pseudocode — the steps cls executes
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hOut, &csbi);
DWORD cells = csbi.dwSize.X * csbi.dwSize.Y;
COORD home = { 0, 0 };
DWORD written;
FillConsoleOutputCharacter(hOut, ' ', cells, home, &written);
FillConsoleOutputAttribute(hOut, csbi.wAttributes, cells, home, &written);
SetConsoleCursorPosition(hOut, home);

Output: (would clear the screen — illustrative, not runnable in cmd)

cls and ANSI colour state#

A common surprise: after running a coloured-output program like winget or git, the console may keep the last colour as the default fill for the next cls. The fix is to emit ESC[0m (reset attributes) before clearing.

# Reset colours, then clear — guarantees a clean white-on-black canvas
Write-Host "`e[0m" -NoNewline
Clear-Host

Output: (screen cleared with default colours)

In cmd.exe, the equivalent is color (no argument) before cls:

color
cls

Output:

(colours reset, then screen cleared)

cls is useless in redirected output#

cls writes to the console handle, not stdout, so capturing it does nothing useful. Worse, mixing it into a script that may sometimes run with redirected output (logging to a file) creates inconsistent files — the cls is invisible in the file but breaks interactive sessions if removed.

rem Bad: this script behaves differently when piped vs interactive
@echo off
cls
echo Build complete.

Output: (none — this is the script body, not invocation)

rem Run the same script interactively vs piped to file
build.bat
build.bat > build.log
type build.log

Output:

Build complete.

The file is correct because cls produced no stdout, but anyone reading the script may assume cls left a marker — it did not.

Conditional clear in batch scripts#

A robust script should clear only when running interactively. Detecting that is awkward in pure cmd.exe, but checking for an empty %CMDCMDLINE% or for a redirected stdout works.

@echo off
rem Only clear if stdout is a TTY (not piped/redirected)
fc nul nul > nul 2>&1
if errorlevel 1 (
    cls
)
echo Starting...

Output:

Starting...

In PowerShell the same idea is one-liner and idiomatic:

if (-not [Console]::IsOutputRedirected) { Clear-Host }
Write-Host "Starting..."

Output:

Starting...

cls and the prompt variable#

cls resets the cursor to the top of the buffer, but the next command will re-emit the prompt. If the prompt contains escape codes (set with prompt $E[36m$P$G$E[0m for a cyan prompt), those colours are re-applied each line. There is no interaction between cls and prompt — but be aware that prompt $E[2J$E[H would create a prompt that clears the screen on every keystroke (almost certainly not what you want).

rem Save and restore the prompt around an inline clear
set OLD_PROMPT=%PROMPT%
prompt $G
cls
echo Hello
prompt %OLD_PROMPT%

Output:

Hello

Animation with cls (don’t do this)#

Calling cls in a tight loop to animate text causes severe flicker because the entire buffer is erased before being repainted. The right way is to use VT cursor positioning (ESC[H) to overwrite specific cells rather than clearing first. Compare:

# Bad — flickers on every frame
while ($true) {
    Clear-Host
    Write-Host "Time: $(Get-Date -Format HH:mm:ss)"
    Start-Sleep -Milliseconds 200
}

Output: (visible flicker)

# Good — overwrite in place, no clear
[Console]::CursorVisible = $false
while ($true) {
    Write-Host "`e[H`e[KTime: $(Get-Date -Format HH:mm:ss)" -NoNewline
    Start-Sleep -Milliseconds 200
}

Output: (smooth update, no flicker)

ESC[H homes the cursor; ESC[K erases the rest of the line. Together they overwrite a single line without touching the rest of the buffer.

Real-world recipes (continued)#

Cross-platform clear in a multi-shell script#

A script that must run identically on Windows PowerShell, PowerShell 7, and Bash (under WSL) can branch on the OS.

if ($IsWindows -or $PSVersionTable.PSVersion.Major -le 5) {
    Clear-Host
} else {
    & clear
}
Write-Host "Starting cross-platform task..."

Output:

Starting cross-platform task...

A reusable function that clears the screen, prints a centred banner, and leaves the cursor below it — useful for batch menus and PowerShell modules alike.

function Show-Banner {
    param([string]$Title)
    Clear-Host
    $width = [Console]::WindowWidth
    $pad   = [Math]::Max(0, ($width - $Title.Length) / 2)
    Write-Host (' ' * $pad + $Title) -ForegroundColor Cyan
    Write-Host ('=' * $width) -ForegroundColor DarkCyan
}

Show-Banner "Deploy: MyApp v2.1.0 — myhost"

Output:

                   Deploy: MyApp v2.1.0 — myhost
================================================================

Refresh-every-second status table#

A common admin pattern — print a live status table that refreshes every second. Using ESC[H instead of cls keeps the screen flicker-free.

[Console]::CursorVisible = $false
try {
    while ($true) {
        Write-Host "`e[H" -NoNewline
        Get-Service | Where-Object Status -eq Running |
            Select-Object -First 10 Name, Status |
            Format-Table -AutoSize | Out-String | Write-Host -NoNewline
        Start-Sleep -Seconds 1
    }
} finally {
    [Console]::CursorVisible = $true
}

Output:

Name            Status
----            ------
AudioEndpoint   Running
BFE             Running
...

Clear-and-prompt utility for batch menus#

A two-line helper used at the top of every menu screen — cleared, banner, blank line, then prompt.

@echo off
:menu
cls
echo === Maintenance Menu ===
echo  1. Disk cleanup
echo  2. Check updates
echo  3. View logs
echo  0. Exit
echo.
set /P pick=Select: 
if "%pick%"=="0" exit /b
goto menu

Output:

=== Maintenance Menu ===
 1. Disk cleanup
 2. Check updates
 3. View logs
 0. Exit

Select:

Clearing inside a remote session#

Invoke-Command against a remote host does not have a real interactive console, so Clear-Host is silently skipped (or throws on older PowerShell). When writing a remote script, omit cls and rely on the caller’s terminal.

Invoke-Command -ComputerName myhost -ScriptBlock {
    # Clear-Host here would do nothing useful
    Get-Service | Where-Object Status -eq Running
}

Output:

Status   Name               DisplayName
------   ----               -----------
Running  AudioEndpoint      Windows Audio Endpoint Builder
...

Sources#

References consulted while writing this article. Links open in a new tab.

See also#