Your terminal. Beautifully configured.
A Windows 11 terminal you actually want to open. One command installs and configures PowerShell 7,
Windows Terminal, a fast prompt, fzf navigation and a cheat sheet. One more gives your Linux servers the same bash.
English · Русский
- Why Termistry
- Install
- Requirements and what gets installed
- Prompt, themes and input
- Git, Docker, Kubernetes and SSH
- Workspace: your projects
- Linux servers
- Customization
- Update, uninstall and backups
- Security
- FAQ
- Development
- License
A fresh PowerShell looks like it was designed for a printer. Doing it by hand takes a while: font, color scheme, prompt, highlighting, completions, a dozen tools, and you always forget something. Termistry does it for you and hands you a cheat sheet for everything it installed. You open the terminal and get to work.
- One palette for everything. Windows Terminal, prompt, input highlighting,
ls, fzf and git diffs share the same colors. Ten themes, switched live. - A prompt that shows what matters and renders in a few milliseconds: folder, git branch with changes, node or python version inside a project, duration of long commands, exit code. The Kubernetes context appears only where it belongs, and in red everywhere when kubectl points at prod.
helpandF1remember commands for you. Abbreviationsg␣→git, up to 50 history suggestions, a fix for commands typed in the Russian keyboard layout.- Workspace: the projects you work on one key away, pinned or recent first, with their servers attached. No disk index, no background work.
- fzf everywhere: folder tree navigation, file previews, live grep, git branches, processes, kubectl contexts.
- Your own commands in any language: a file in
bin\becomes a command, Python or Rust alike. - Your servers get the same prompt, cheat sheet and a guard against
docker compose down -v. Nothing is installed there and nothing runs in the background. - English and Russian interface, switched with
lang en/lang ru. - Running it again is safe. That is also how you update.
Open PowerShell (a regular one, not as administrator) and run:
irm https://raw.githubusercontent.com/Ange1oc/termistry/master/install.ps1 | iexThe script asks for the language (en or ru), installs PowerShell 7 if it is missing and continues there. It asks for administrator rights once: the icon font has to be installed for all users, otherwise Windows Terminal cannot see it. When it is done, close all terminal windows, open a new one and press F1.
Prefer to read the script before running it? See Verified install.
Parameters
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/Ange1oc/termistry/master/install.ps1))) -Lang en -Theme gruvbox -SshTabs prod,staging| Parameter | What it does |
|---|---|
-Lang en|ru |
interface language, later changed with lang |
-Theme <name> |
theme, later changed with theme |
-StartingDirectory D:\code |
folder a new tab opens in |
-SshTabs host1,host2 |
tabs in the Windows Terminal menu for hosts from ~/.ssh/config |
-SkipApps |
configs only, no programs or font |
-Uninstall |
remove everything of its own, keep custom.ps1, bin\, programs and *.bak files |
-ProfileDir D:\pwsh |
put the profile files somewhere other than the $PROFILE folder (the tests use it) |
setup-terminal.ps1 is a single self-contained file. Every release publishes it together with SHA256SUMS, so you can download a fixed version, check it, read it and only then run it:
$v = 'v1.1.0'
$dir = New-Item -ItemType Directory -Force "$env:TEMP\termistry-$v"
foreach ($f in 'setup-terminal.ps1', 'SHA256SUMS') {
Invoke-WebRequest "https://github.com/Ange1oc/termistry/releases/download/$v/$f" -OutFile "$dir\$f" -UseBasicParsing
}
$expected = ((Get-Content "$dir\SHA256SUMS") -match 'setup-terminal\.ps1$' -split '\s+')[0]
if ((Get-FileHash "$dir\setup-terminal.ps1" -Algorithm SHA256).Hash -ne $expected) { throw 'Checksum mismatch' }
notepad "$dir\setup-terminal.ps1" # read it
powershell -ExecutionPolicy Bypass -File "$dir\setup-terminal.ps1" # then run itOr build it yourself from source: git clone https://github.com/Ange1oc/termistry, then .\build.ps1 and .\setup-terminal.ps1. Offline machines only need that one file.
Requirements
- Windows 11 with winget ("App Installer" from the Microsoft Store). Windows 10 is not tested.
- Windows PowerShell 5.1 or PowerShell 7 to start the installer. The profile itself runs in PowerShell 7.
- Internet access and one administrator confirmation (UAC) for the font.
- For servers: Linux with bash 4 or newer and SSH access. Docker is optional.
What gets installed (via winget, only what is missing)
| Shell and terminal | PowerShell 7, Windows Terminal |
| Tools | git, fzf, zoxide, eza, bat, ripgrep, fd, delta, lazygit, tldr, gh |
| PowerShell module | PSFzf from the PowerShell Gallery |
| Font | JetBrainsMono Nerd Font v3.4.0, for all users |
What gets configured
| PowerShell profile | ~\Documents\PowerShell\: prompt, themes, commands, completions, history suggestions |
| Windows Terminal | PowerShell 7 by default, theme, font, padding, `Win+`` drops the terminal over any window, optional SSH tabs |
| VS Code | the same font in the integrated terminal |
| git | diffs through delta in the terminal colors |
The profile starts in about half a second: only the core loads up front, while the command dictionary, completions and zoxide load right after the prompt is on screen.
The prompt is rendered by PowerShell itself, no external programs: the branch is read from .git/HEAD, the Kubernetes context from kubeconfig, and git status counts are fetched in the background and drawn in once they are ready.
help shows everything by section, help git one section, help docker searches the text. F1 opens the same cheat sheet in fzf: find a command, press Enter, it is in the input line.
theme gruvbox, and the terminal, prompt, input highlighting, fzf and diffs switch at once, in every open tab. Included: Catppuccin Mocha, Macchiato, Frappe and Latte (light), Black for OLED, Gruvbox Dark, Dracula, Tokyo Night, Nord, Rose Pine. theme without a name lists them.
lang ru switches help, my and every message to Russian, lang en back to English. Servers pick it up on the next srv install.
| start typing | up to 50 suggestions from history (PSReadLine's built-in limit is 10), ↑/↓ scroll, → accepts |
g␣ k␣ d␣ dc␣ |
abbreviations expand on space into git, kubectl, docker, docker compose. History keeps the full commands |
вщслук зы ⏎ |
a command typed in the Russian layout is fixed and executed as docker ps |
Tab |
completions for kubectl, helm, docker, gh, kind, k3d, minikube and ssh hosts, cached so startup does not pay for them |
Ctrl+R · Ctrl+T |
fzf: history search, insert a file path with a preview |
Alt+C · nav |
folders as a tree with a preview pane: → enter, ← up, Enter go, Ctrl+E show files too, Ctrl+H hidden, Ctrl+F fuzzy search through every folder below, Ctrl+O open in Explorer |
z <part> |
jump to a frequently used folder (zoxide) |
pv · rgi TODO |
files with a preview pane · live grep: type and the list updates, Enter opens the file at that line |
pk node · o file |
pick a process and kill it · open with the default app |
h · h docker |
last 50 commands, 10 per page, optionally filtered |
Ctrl+Backspace · Ctrl+Z · Shift+Enter |
delete word, undo, new line without running |
my sys · my ssh · my ports 5432 · my ip public · my k8s · my docker · my tools · my path · my git · my cmds · my config · my keys
Small helpers that exist on the server too: ex archive extracts zip, tar.gz, 7z; bak file makes a copy before editing; psg node finds processes; ll | cb puts the output into the clipboard.
| Git | branch and change counters in the prompt, gst, lg, gbr (branches with their log, Enter switches), lazygit, diffs through delta, my git |
| Docker | my docker lists containers and compose projects, completions for docker, d␣ and dc␣ abbreviations |
| Kubernetes | the context shows in folders with Chart.yaml, kustomization.yaml, k8s/, helm/ and similar, and always in red for prod. kctx and kns switch context and namespace from a list, my k8s shows them all. $Termistry.Kube = 'always' or 'off' changes when it is shown |
| SSH | my ssh lists hosts from ~/.ssh/config, jump picks one and connects, ssh <Tab> completes host names, -SshTabs adds hosts to the Windows Terminal menu, srv installs the server bash |
When there are hundreds of repositories on the disk and a dozen of them are in use, work keeps those at hand. It is a short list you curate, not an index: nothing scans the disk, nothing runs in the background, and nothing is added unless you ask.
work add # add the project you are in (its git root)
work # pick a project, Enter goes there
work api # a name with one match goes straight there
work pin # pinned projects come first and get a star in the prompt
work import D:\code # find projects in a folder (3 levels) and pick which to add
work import # the same among folders you have visited (zoxide history)work [name] |
fzf picker: pinned first, then by how often you visit them (zoxide), then by name, with a preview of the folder. Enter goes there, Ctrl+O opens it in the editor, Ctrl+P pins or unpins, Ctrl+S connects to its server, Ctrl+D drops it from the list (the files stay) |
work add [folder] · work rm [name] |
add the project you are in, or a folder · drop one from the list |
work pin · work unpin [name] |
pin or unpin the current project or one by name |
work import [folder] [-Depth 3] |
look for project folders and pick which to add: .git or a marker file makes a folder a project, which is not looked into; hidden, node_modules, target, bin, obj and other build folders are skipped |
work . · work list · work clean |
what Termistry knows about this project · the whole list · drop projects whose folder is gone |
In the prompt the folder icon shows where you are: a folder in a plain folder, a bookmark inside a listed project, a star in a pinned one. Nothing else is added. The versions of node, python, go and rust and a docker icon come from marker files in the folder and in its git root, so they also show in subfolders.
A project is its git root, or a folder with a marker file: package.json, pyproject.toml, requirements.txt, go.mod, Cargo.toml, compose.yaml, docker-compose.yml, Dockerfile, pom.xml, build.gradle, composer.json, Gemfile. Add your own in custom.ps1: $ProjectMarkers['mix.exs'] = 'elixir'.
SSH environments. A project can have servers attached to it, each with a remote folder:
work ssh add prod web-1 /srv/shop # an alias from ~/.ssh/config and the folder on the server
work ssh add staging staging ~/shop
work ssh prod # ssh web-1, cd /srv/shop, your login shell
work ssh # one environment connects at once, several open a list
work ssh rm stagingNothing connects by itself and nothing is checked over the network. Only the host alias and the folder are stored, never passwords or keys. The folder is quoted for the remote shell, so it cannot run anything, and the host name cannot start with -. On a server set up with srv you land in the same bash.
Storage. ~\.config\termistry\projects.tsv (path, pin, types) and projects-ssh.tsv, plain text with one line per project. Every change takes a lock, re-reads the file and replaces it in one move, so several open terminals never overwrite each other; they notice each other's changes within 2 seconds. -Uninstall keeps both files.
Speed. The prompt now works out a folder once, when you enter it, and afterwards only compares the timestamps of the folder and its git root; the branch and kubeconfig are read with direct file calls. The list is read once and again only when the file changes. Measured with tests\bench.ps1 on one Windows 11 machine with real-time antivirus, where every file check costs about 0.15 ms:
| before Workspace | with Workspace | |
|---|---|---|
| prompt in the same folder, repository root | 15.0 ms | 1.7 ms |
| prompt in the same folder, deep inside a repository | 16.9 ms | 2.0 ms |
| first prompt in a folder | 9.3 ms | 10.5 ms |
| prompt with 10 000 projects in the list | - | 1.4 ms |
| reading a list of 10 000 projects (when it changes) | - | 73 ms |
work picker lines for 1 000 / 10 000 projects, zoxide included |
- | 133 / 528 ms |
| profile load | 680-720 ms | 690-720 ms |
Limits. Recent-first order needs zoxide, which Termistry installs; without it, pinned projects come first and the rest by name. On network drives only the git root is found: types and k8s folders are not checked, so the prompt never waits on the network. A project without git is recognized in its own folder only, and anywhere inside it once it is in the list. .NET projects (*.csproj) have no fixed file name and are not detected by type. work clean keeps projects on a drive that is not connected right now.
$Termistry.Workspace = $false in custom.ps1 removes the marks from the prompt; work keeps working.
srv install prod -Env prod # install or update, with a label in the prompt
srv install # no host: pick one from ~/.ssh/config
srv remove prod # roll backOne ssh connection, a backup and a trial load before anything is replaced, one line added to ~/.bashrc. Running it again breaks nothing. Not a single program is installed and not a single background process is started on the server, only functions in your shell. That is why it is fine on production.
- Projects are discovered with
docker compose lsand remembered. Each gets a command of its own name:shop,shop logs web,shop sh web,shop restart web. Tab completes services.projlists all projects,proj addadds a folder by hand. - A prompt with an environment label (
prodred,stagingyellow,devgreen), git branch, duration of long commands and exit code. - Guards:
docker compose down -v,volume rm,system prunerequire typingyes;rm,cp,mvask before mass changes. Scripts are unaffected. sysshows load, memory, disk, processes and containers.helpsearches the cheat sheet.bak,ex,psg,hwork the same way as on Windows.- Per-server settings live in
~/.config/bashrc-local.conf(PROMPT_ENV=prod,LANG_UI=en). - Your own files for servers:
server\custom\*.shnext to the profile go to every server into~/.bashrc.d/.helpon the server also lists scripts from~/bin(caption from a# help: …line) and functions from~/.bashrc.d/*.sh.
Your own commands in any language. A file in bin\ next to the profile is a command:
new weather.py 'weather in a city' # creates bin\weather.py from a template and opens it in VS Code
weather Berlin # already a command, no restartA # help: … line at the top becomes its caption in help and my cmds. The extension picks the runner: .py via uv (dependencies right in the file, # /// script), .ps1, .js, .ts (bun, deno or node), .sh, .go, .rs (rust-script), .clj (babashka), .rb, .lua, .php. A compiled .exe just goes into bin\. A taken name is never overridden: new git.py refuses, and a file named after a real program yields to it.
custom.ps1 in the same folder holds your functions, abbreviations and switches. It loads last, is never overwritten, and its functions show up in help. ep opens the profile folder in VS Code.
$Termistry.Abbreviations = $false # turn off g␣ → git␣
$Termistry.LayoutFix = $false # turn off the keyboard layout fix
$Termistry.Predictions = 20 # number of history suggestions
$Termistry.Kube = 'always' # Kubernetes context: auto, always, off
$Termistry.Workspace = $false # no Workspace marks in the prompt
abbr gcm 'git commit -m "%"' # % marks the cursor
function deploy { ssh prod 'cd app && git pull && docker compose up -d' } # shows up in helpYour own theme. Every theme is one block in palette.ps1: copy one, change the colors, run theme <name>.
Where things live. my config lists every path with a check mark, doctor verifies that everything is in place and working.
~\Documents\PowerShell\ |
profile and commands, your custom.ps1, bin\, server\custom\. This is the $PROFILE folder; with Documents redirected to OneDrive it lives there and syncs between machines |
~\.config\termistry\ |
theme, lang, the Workspace list projects.tsv and projects-ssh.tsv |
~\.cache\termistry\, ~\.cache\pwsh-* |
caches, safe to delete, rebuilt automatically |
%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_*\LocalState\settings.json |
Windows Terminal |
%APPDATA%\Code\User\settings.json, ~\.gitconfig |
VS Code terminal font, delta for git |
-
Update:
updatedownloads the installer from this repository and updates whatever changed. Running the install command again does the same. -
Backups: profile files, Windows Terminal and VS Code settings that differ from the new version are saved next to themselves as
*.bak-<date>before being replaced. git settings are changed withgit config. Yourcustom.ps1andbin\are never touched. -
Uninstall: removes the profile files and caches; programs, the font,
custom.ps1,bin\, the Workspace list and*.bakfiles stay.& ([scriptblock]::Create((irm https://raw.githubusercontent.com/Ange1oc/termistry/master/install.ps1))) -Uninstall
-
Servers:
srv remove <host>restores the server~/.bashrc. -
Coming from terminal-setup: Termistry is the new name of terminal-setup. Run the install command once: your theme and language move from
~\.config\terminal-setupto~\.config\termistry, and acustom.ps1that uses$TerminalSetupkeeps working.
- The installer runs as a regular user and asks for elevation only to install the font machine-wide.
- Programs come from the official winget source, PSFzf from the PowerShell Gallery, the font from a pinned Nerd Fonts release. Nothing else is downloaded.
- No telemetry, no background services, no scheduled tasks.
- On servers nothing is installed:
srv installcopies shell files over your own ssh connection, backs up the files it replaces, checks their syntax and loads them in a trial shell before switching. irm … | iexruns code from the internet. If that is not acceptable, use the verified install.
Found a vulnerability? Please report it privately through GitHub security advisories instead of a public issue.
No winget? Install "App Installer" from the Microsoft Store and run the command again. Or run with -SkipApps and install the programs yourself.
Does it change Windows PowerShell 5.1? No. The profile lives in the PowerShell 7 folder; Windows PowerShell keeps its own.
Can I skip the icon font? Yes, you get Cascadia Mono and boxes instead of icons. The script warns you.
I broke custom.ps1 and the terminal complains on start. The profile survives it and loads anyway. doctor shows the line with the error.
Startup feels slow. doctor measures it. Completions are cached; after updating a CLI run Update-Completions.
I do not need the Russian parts. Choose en at install time or run lang en. The keyboard layout fix only reacts to commands typed in the Russian layout and can be turned off with $Termistry.LayoutFix = $false.
install.ps1 one-line installer: downloads setup-terminal.ps1 and runs it
setup-terminal.ps1 everything in one file, built from src/, do not edit by hand
build.ps1 .\build.ps1 · .\build.ps1 -FromProfile pulls the setup from this machine
src/
setup-logic.ps1 installer logic
profile/ profile, prompt.ps1, palette.ps1 (themes), lang.ps1 (en/ru strings),
toolkit.ps1 and toolkit-lazy.ps1 (commands), workspace.ps1 (work), history suggestions plugin
server/ bashrc.local, inputrc and the installer behind srv
tests/ .\tests\run.ps1: profile, prompt, installer and server bash, all in a sandbox
tools/ make-screenshots.ps1 and record-demo.ps1: the images in docs/ come from real output
.\tests\run.ps1runs every check without touching your real profile;-Only static,profile,setup,serverpicks parts. The server part needs WSL; CI runs it on Ubuntu withbash tests/server.sh src/server.- After changing anything in
src\, run.\build.ps1and commitsetup-terminal.ps1too; CI fails if it is out of date. .\tools\make-screenshots.ps1 -Lang enregeneratesdocs\*.png,.\tools\record-demo.ps1recordsdocs\demo.giffrom a real Windows Terminal window,-Session workspacerecordsdocs\workspace.gif..\tests\bench.ps1measures the prompt and the Workspace list;-Profile <folder>measures another copy, for example an older checkout, to compare.- User-facing strings live in
src\profile\lang.ps1andsrc\setup-logic.ps1in both languages; keep them in sync.
Issues and pull requests are welcome.
Termistry is released under the 0BSD license: use, copy, modify and distribute it for any purpose, no attribution required.
The programs, PowerShell module and font that the installer downloads are not part of this repository and keep their own licenses. Theme palettes follow the published color schemes of Catppuccin, Gruvbox, Dracula, Tokyo Night, Nord and Rosé Pine.







