A GitHub Copilot CLI extension for the GitHub Copilot desktop app and other Canvas-capable Copilot hosts. It opens a Canvas showing every PowerShell command Copilot runs in your session, along with its output, rendered console-style in real time.
The extension hooks into Copilot CLI's tool lifecycle and shows entries for every call to:
powershell(sync and async commands)write_powershell(input sent to a running session)read_powershell(buffered output reads)stop_powershelllist_powershell
Each command renders as a collapsible entry tagged with a small status
circle (green = success/active/stopped, pulsing green = pending). The renderer
also supports red failure/rejected/denied/unknown states when a result supplies
one. Hover the circle to see the exact status.
Calls and results are paired into a single entry, with the input text
(prefixed with PS>) and the captured output stacked underneath.
Async sessions get special treatment: see Sessions below.
- Windows 10 / 11 for the provided install scripts.
- One of these signed-in, Canvas-capable hosts:
- The GitHub Copilot desktop app, which supplies its embedded Copilot CLI runtime.
- GitHub Copilot CLI used from a host that supports extension Canvas rendering.
- (Only when installing with
-FromGitHub)gitonPATH, or GitHub CLI (gh auth login) for tarball fallback / private-repo access.
You can install the extension per-project (only available in one repo) or globally (available to your user account across projects in supported Copilot hosts).
Clone the repo once, then run the installer. The script copies your current working tree into the discovery directory — modifications, untracked files, and feature branches are all preserved.
git clone https://github.com/pacovidal/copilot-ps-console-view.git
cd copilot-ps-console-view
# Per-project (current directory must be inside a git repo)
.\scripts\install.ps1 -ProjectPath C:\path\to\my\project
# Or globally
.\scripts\install.ps1 -Scope GlobalThis places the extension at either:
<project>\.github\extensions\copilot-ps-console-view\(per-project — the project must be a git repository for Copilot CLI to discover it), or%USERPROFILE%\.copilot\extensions\copilot-ps-console-view\(global).
You can delete the original clone afterwards; the installed copy is self-contained.
To install in one line, without cloning, fetch the bootstrap script and
pipe it to iex. It will ask whether you want a per-project or global
install:
irm https://raw.githubusercontent.com/pacovidal/copilot-ps-console-view/main/scripts/install-remote.ps1 | iexFor non-interactive installs, or to override defaults like -Ref or
-RepoUrl, download the bootstrap to disk and invoke it directly. Any
arguments are forwarded to install.ps1 (with -FromGitHub already set),
and passing any argument suppresses the interactive prompt:
$bootstrap = "$env:TEMP\cpcv-install-remote.ps1"
irm https://raw.githubusercontent.com/pacovidal/copilot-ps-console-view/main/scripts/install-remote.ps1 -OutFile $bootstrap
# Globally
& $bootstrap -Scope Global
# A specific branch / tag
& $bootstrap -Ref my-feature-branchIf you already have a clone and just want to skip the local-copy default,
run .\scripts\install.ps1 -FromGitHub directly. -Ref and -RepoUrl
imply -FromGitHub if you pass them without it.
| Parameter | Default | Notes |
|---|---|---|
-Scope |
Project |
Project or Global |
-ProjectPath |
current dir | Only used when -Scope Project |
-FromGitHub |
off | Fetch from GitHub instead of using the local working tree |
-Ref |
main |
Only used with -FromGitHub. Branch or tag |
-RepoUrl |
this repo | Only used with -FromGitHub. Override for forks / mirrors |
-Force |
off | Overwrite an existing install |
The extension registers a Canvas named PowerShell Console.
After installing or updating the extension:
-
Reload Copilot CLI (
/reload-extensionsor restart the CLI). You'll see a message confirming the extension is loaded. -
Open the console Canvas with the slash command.
/ps-console-viewYou can also ask the agent:
Open the PowerShell console canvas -
While open, the Canvas streams every PowerShell command Copilot runs. Run
/ps-console-viewagain to reopen or focus it.
New sessions discover installed extensions automatically. For an existing session, open the command palette and run Refresh canvas; restart the app if the extension still does not appear.
Open PowerShell Console using any of these methods:
-
Enter the slash command or ask the agent:
/ps-console-viewOpen the PowerShell console canvas -
In the right panel, select + → Extensions → PowerShell Console.
While open, the Canvas streams every PowerShell command Copilot runs. It auto-scrolls and supports word-wrap. Use Clear to reset both the on-screen log and the in-memory history buffer.
When Copilot starts a long-running shell with powershell --mode=async, the
console renders it as a session entry instead of a simple paired entry.
Subsequent write_powershell, read_powershell, and stop_powershell calls
that target the same shellId are folded into the session's body as a
transcript — one labelled line per interaction:
- Started — the initial command and its captured startup output
- Sent — input written into the session
- Read — output read back from the session (deduped: only new content since the previous read/write is shown)
- Stopped — when the session is explicitly stopped
The header shows the status circle (pending → active → stopped), the
shell=<id> chip, the start time, and a live duration that ticks while
the session is active and freezes once it stops.
list_powershell calls are noisy, so they're hidden by default and
render as a single-line entry (Listed N active session(s)) when shown.
Right-click → Show list_powershell entries to toggle them on.
If a write_powershell/read_powershell/stop_powershell call references
a shellId whose start was never observed (extension reloaded mid-session,
history aged out, etc.), it renders as an "orphan continuation" mini-entry
tagged with the missing shellId rather than crashing or being attached to
an unrelated session.
The console ships with seven built-in colour schemes (default-dark,
default-light, solarized-dark, solarized-light, campbell, one-half-dark,
tango-dark) and picks default-light or default-dark on first run based
on your OS appearance preference.
Switch themes via the right-click context menu → Theme ▸. Your choice is remembered across sessions.
To add your own theme, drop a .css file into:
<extension-install-dir>\themes\(default; preserved across upgrades), or- the directory pointed at by
$env:COPILOT_PS_CONSOLE_THEMES_DIR.
Reopening the Theme submenu picks up new files automatically. See
content/themes/README.md for the variable
reference and a copy-pastable starter template.
The extension currently receives result entries only from onPostToolUse.
Failed, rejected, denied, or timed-out calls may remain shown as pending until
Clear or a full Canvas state rebuild.
A small dim diamond next to a tool name means the call entry was
reconstructed from the result, because the live "tool starting" hook never
reached this extension. This is caused by an upstream Copilot CLI bug:
runAgenticLoop snapshots its hooks once at loop start, and after an
extensions_reload mid-loop the snapshot still references the dead old
extension's IPC connection. Subsequent preToolUse invocations silently
fail. The result still arrives via the live postToolUse path, so the
extension synthesizes a placeholder call event from the post hook's
arguments and pairs it. The command + output are accurate; only the live
"running" view was missed. Fixed automatically on the next user prompt
(which restarts runAgenticLoop and refreshes the snapshot).
When two PS calls have byte-identical summarized arguments AND their
results arrive out of pre-hook order (one fails so its post never fires,
or two parallel read_powershell calls with the same shellId + delay
complete out of order), the pair-matching can swap their entries — call A
will display result B and vice versa. Single isolated mispair, no broader
poisoning.
Set COPILOT_PS_CONSOLE_DEBUG=1 in your shell environment before
launching Copilot CLI to enable a JSONL diagnostic log at
<extension-install-dir>\_debug.log. Useful for filing issues if you
see unexpected behavior.
# Per-project (run from inside the project)
.\scripts\uninstall.ps1
# Global
.\scripts\uninstall.ps1 -Scope Globalgit clone https://github.com/pacovidal/copilot-ps-console-view.git
cd copilot-ps-console-view
npm testFor local hacking, symlink (or copy) the working tree into the discovery folder:
# project-scoped
New-Item -ItemType Junction `
-Path "C:\path\to\project\.github\extensions\copilot-ps-console-view" `
-Target "C:\path\to\copilot-ps-console-view"After extension-side edits, run /reload-extensions in Copilot CLI or
Refresh canvas in the GitHub Copilot app. For content-only changes, close
the Canvas and open it again.
copilot-ps-console-view/
├── extension.mjs # extension entry point
├── main.mjs # Canvas registration, hooks, callbacks
├── lib/ # tokenized HTTP/RPC/SSE content server
├── content/ # the Canvas page
│ ├── bridge.js # JSON RPC + SSE browser bridge
│ ├── console-lifecycle.js
│ └── themes/ # built-in themes + author guide
├── scripts/ # install.ps1, uninstall.ps1
├── tests/ # transport, bridge, and lifecycle tests
├── package.json
├── LICENSE # MIT
└── README.md
MIT — see LICENSE.

