All Eyez on your environment.
A persistent Power Platform CLI (pac) statusline pinned to the top of your terminal.
Always know who you're logged in as, which tenant, which environment, and which solution
you're working on — before you run that pac solution import against the wrong org.
A colleague started living in the Power Platform CLI and kept hitting the same
wall before every command: which environment am I actually pointed at right
now? The honest way to find out is pac org who — six seconds, one network
round-trip, and a small prayer that the answer isn't "Production." He wanted that
answer pinned to the top of his terminal: always on, no round-trip, no
praying.
"Can't you just... make that?"
Reader, this is "just make that."
The name wrote itself. pac + a statusline keeping All Eyez on your
environment left no responsible alternative to naming it after 2Pac's Pac's
Life. Yes, really. Roll the tape:
pac org whotakes 6+ seconds (network round-trip). PacLife reads pac's local auth store and renders in milliseconds — no network calls, ever.- The statusline refreshes after every command: run
pac auth selectorpac env selectand the top row updates immediately. - Production gets the red treatment: environments of type
Production/Default— or any URL you mark as protected — show a red segment stating why:⚠ Production,⚠ Default Environmentor⚠ Protected. - Service principals are unmistakable: SPN auth renders on a purple segment with the AppId, so a CI/consultant identity is never mistaken for you.
- Sovereign clouds stand out: GCC / GCC High / DoD / China get a high-visibility magenta segment.
irm https://raw.githubusercontent.com/Gakinchi/paclife/main/install.ps1 | iexInstalls the latest GitHub Release into your user module path and adds an activation block to your PowerShell profile.
Requirements: a VT-capable terminal (Windows Terminal, VS Code terminal, iTerm2, ...). Works on both PowerShell 7+ and Windows PowerShell 5.1 — it's the terminal that matters, not the shell. In a legacy console without VT support, PacLife simply stays quiet.
| You type | Which is | What it does |
|---|---|---|
paclife |
Show-PacLife |
print the compact context line once |
alleyez |
Show-PacLife -Full |
All Eyez on Me — the full detail banner |
keepyaheadup |
Enable-PacLife |
pin the statusline to the top (+ profile) |
lifegoeson |
Disable-PacLife |
turn it off and restore the terminal |
changes |
Update-PacLife |
update to the latest release |
Get-PacContext |
the context as an object, for your own scripts | |
Get-PacLifeStatusLine |
the context as one line, for an AI agent's statusline (see below) |
| Segment | Source |
|---|---|
| Identity | user UPN (blue) or service principal AppId (purple, SPN) |
| Environment | friendly name, colored red (Production/Default/protected), green (Sandbox/Developer/Trial), yellow (unknown or no environment selected) |
| Auth kind | only shown for legacy DATAVERSE/ADMIN profiles (explains why some pac commands fail despite being "logged in") — the modern UNIVERSAL default is hidden |
| Geo / cloud | the environment's region (EMEA, dim); the cloud appears only when sovereign (GCC High, magenta) — the default Public cloud is hidden |
| Solution | detected from your working directory (.cdsproj, src/Other/Solution.xml, .pcfproj — searched upward, like git finds .git), with its version: sln ContosoCore 1.2.0.3 |
| Profiles | 4 profiles — shown when you have more than one to switch between (pac auth list; details in alleyez) |
| pac version | the locally installed CLI version |
The terminal tab title is set to the environment name too, so you can tell your tabs apart.
If you use oh-my-posh, PacLife reads your active theme
(via POSH_THEME, offline — it never runs oh-my-posh.exe) and restyles itself to match:
- Colors: segments adopt your theme's palette, rendered in exact 24-bit truecolor.
- Shape: diamond-style themes (like atomic) get diamond-capped segments; powerline themes get their own separator glyph.
- Semantics stay sacred: the environment segment keeps its red/green/yellow meaning, but uses your theme's own red/green/yellow shades (with built-in fallback when the theme has no matching hue). Theme matching changes nuances, never meaning.
JSON themes only — YAML/TOML themes silently fall back to the built-in palette.
Set "theme": "builtin" to opt out.
{
"protectedUrls": ["*contoso-prod*", "*.crm4.dynamics.com/"],
"safeUrls": ["*playground*"],
"windowTitle": true,
"theme": "auto",
"style": "auto"
}protectedUrls— wildcard patterns that force the red treatment regardless of environment type (for that production org someone created as a Sandbox...).safeUrlsmutes it.theme—"auto"(match oh-my-posh when present),"builtin", or a path to an.omp.jsonfile.style—"auto"(follow the theme),"powerline","diamond", or"plain".NO_COLORenvironment variable is honored.
- PacLife shows the last known context — a mirror of what pac last wrote to disk.
It never claims live status and never makes a network call (only
changes/install.ps1touch the network, because you asked them to). - The "context last refreshed ≈ ..." line in
alleyezis derived from the cached token timestamp. An old date does not mean you must re-authenticate — pac renews tokens silently. - Logged in ≠ connected to an environment. If you're authenticated without an environment, PacLife says so on a yellow segment instead of pretending.
No problem — PacLife wraps your prompt function and calls it through, so both render.
Just make sure the PacLife block stays last in your $PROFILE (the installer puts it there).
The pinned top row works by owning a terminal scroll region and repainting itself on every PowerShell prompt. A full-screen TUI agent — Claude Code CLI, GitHub Copilot CLI, Cursor CLI — takes over the whole screen, resets the scroll region, and stops the prompt loop, so the pinned banner disappears for the length of the session. Two programs can't own the same surface; this is structural, not a bug (it's the same reason vim/less disturb the top row — except here the prompt doesn't come back until you quit the agent).
The fix is to stop fighting for row 1 and ride the agent's own statusline instead.
All three agents support a custom statusline: they run a command and render its stdout at
the bottom of their UI. Get-PacLifeStatusLine is exactly that command's payload — the
same compact, theme-aware line, on one row. It reads pac's auth store directly, so it
needs nothing from the agent.
A ready-made launcher lives at agents/paclife-statusline.ps1
(it discards the session JSON the agent pipes in and prints the line).
Claude Code renders multiple lines, so the cleanest setup is to compose PacLife as a
second line under whatever your statusline already shows. If you already have a
statusLine script, append:
Import-Module PacLife -ErrorAction SilentlyContinue
if (Get-Command Get-PacLifeStatusLine -ErrorAction SilentlyContinue) {
"`n" + (Get-PacLifeStatusLine)
}If you have no statusline yet, point ~/.claude/settings.json straight at the launcher:
{
"statusLine": {
"type": "command",
"command": "powershell -NoProfile -File C:/Users/you/.claude/paclife-statusline.ps1"
}
}(or run /statusline in Claude Code and describe what you want).
Custom statuslines are behind the experimental flag. Add to ~/.copilot/settings.json:
{
"experimental": true,
"statusLine": {
"type": "command",
"command": "powershell -NoProfile -File C:/Users/you/.copilot/paclife-statusline.ps1"
}
}Then, inside Copilot CLI, run /statusline, toggle custom on, and /restart.
Cursor's custom-command statusline is experimental and its config schema isn't officially
documented yet, so the reliable path is the in-CLI helper: run /statusline in Cursor
and point it at the launcher, e.g.
powershell -NoProfile -File C:/Users/you/.cursor/paclife-statusline.ps1.
Heads-up: Each agent spawns a fresh PowerShell per refresh, so the line adds a small
Import-Modulecost. PacLife's reads are mtime-cached and never hit the network, so it stays well within a statusline budget.
lifegoeson # turn off + remove from profile
# or remove everything:
irm https://raw.githubusercontent.com/Gakinchi/paclife/main/uninstall.ps1 | iexWhy doesn't it show whether my token is still valid? Because it can't know without a network call, and a statusline that makes network calls on every prompt is a statusline you'll uninstall by lunch. See Honesty notes.
The top row got messed up by a full-screen app (vim, less). It heals on your next prompt — the scroll region and statusline are re-asserted every time.
Does it send telemetry? No.
MIT — see LICENSE.

