Your editor already does snippets, and does them better than any system-wide tool: it knows the language, it places the cursor, it fills in placeholders and tabs between them.
So the question is not whether to use snippets. It is what belongs in the other layer, the one that works in the terminal, the browser, the pull request review box, the ticket, the chat window and the commit message editor. Those are five windows your editor's snippet engine does not reach, and together they hold a surprising share of the day's typing.
One rule for what belongs here
Expand what is invariant. Leave what is contextual to the editor.
A system-wide expander replaces a trigger with fixed text. It has no cursor placement and no fill-in fields, so anything that needs you to land in the middle and type a variable is the wrong shape for it. That is an editor snippet, and it is better there anyway.
What is left is larger than it sounds: strings that are identical every single time. Applied honestly, the rule excludes most code-shaped snippets and includes a lot of infrastructure, prose and ceremony.
Git and the shell
Commands you type dozens of times that are too specific for a shell alias, or that you want on machines where your dotfiles are not.
| Trigger | Expands to |
|---|---|
;gst |
git status -sb |
;glog |
git log --oneline --graph --decorate -20 |
;gcb |
git checkout -b |
;gpo |
git push -u origin HEAD |
;kx |
kubectl get pods -o wide |
;dcu |
docker compose up -d --build |
;dprune |
docker system prune -af --volumes |
The last two are the argument for the whole category: destructive or fiddly commands you type rarely enough to look up and often enough to resent looking up.
Logging and debugging
| Trigger | Expands to |
|---|---|
;log |
console.log('') |
;pp |
print(f"{=}") |
;pdb |
import pdb; pdb.set_trace() |
;bp |
debugger; |
;todo |
// TODO(yourname): |
;fixme |
// FIXME(yourname): |
;todo earns its place because of the name in it. A TODO with an owner is findable and a TODO without one is landfill, and the reason people leave the name out is that it is four extra characters at the exact moment they are thinking about something else.
Things you type in a browser
This is where the system-wide tool wins outright, because your editor's snippets are not here.
| Trigger | Expands to |
|---|---|
;lh |
http://localhost:3000 |
;lh8 |
http://localhost:8080 |
;sturl |
your staging host |
;repo |
the repository URL |
;ci |
the build you check most often |
Long internal URLs that are not quite memorable and not quite bookmarkable are among the highest-value entries and the ones people forget to add.
Code review and pull request prose
The sentences you write over and over, where the value is consistency of tone rather than saved keystrokes.
| Trigger | Expands to |
|---|---|
;nit |
nit: non-blocking, feel free to ignore — |
;lgtm |
LGTM. One small thing below, otherwise ship it. |
;why |
Could you add a comment on why this is needed? The what is clear from the code. |
;test? |
Worth a test for the failure path here? |
A one-word prefix marking a comment as non-blocking prevents a whole category of review friction, and it only does that if typing it is frictionless.
Ceremony and chat
| Trigger | Expands to |
|---|---|
;pr |
PR is up and ready for review: |
;deploy |
Deploying to production in 5 minutes — shout if that's a problem. |
;rb |
Rolling back. Investigating, will update in 15. |
;oncall |
I'm on call this week — ping me directly for anything urgent. |
One constraint here. In Slack, Teams and Discord, Enter sends the message, so a multi-line snippet arrives as several messages. Keep multi-line entries for editors and mail, or type the trigger and press Space rather than Enter and let the app's Shift+Enter handle the line breaks.
Strings that are annoying to type correctly
| Trigger | Expands to |
|---|---|
;uuid0 |
00000000-0000-0000-0000-000000000000 |
;shebang |
#!/usr/bin/env python3 |
;iso |
{date:yyyy-MM-dd} |
;stamp |
{datetime:yyyy-MM-dd HH:mm:ss} |
;arrow |
→ |
;chk |
✓ |
The date macros resolve when you type, not when you created the snippet, so ;iso is today's date every day. That makes it usable in branch names, changelog entries, log lines and file names.
Emoji need no snippet at all: :rocket:, :fire:, :+1: and around 1,900 other shortcodes are built in and fire on the closing colon.
Triggers you will still remember in March
The failure mode of a snippet library is not that it is too small. It is that it grows to eighty entries and you use twelve, because you cannot recall the other sixty-eight.
- Prefix by domain, strictly.
;gfor git,;dfor docker,;kfor kubernetes,;rfor review,;ufor URLs. Wanting a git thing, you type;gand the rest is a short guess in a small space. - Make the trigger the abbreviation you would say out loud.
;gstworks because you already think of it that way.;g1does not. - Use a prefix character that never starts a real word. A leading
;is the convention for a reason: no English or code token begins with it, so a trigger cannot fire inside a word by accident. - Never define a trigger that is a real word.
;logis safe.logis not. - Add the snippet the third time, not the first. The first is a coincidence, the second a pattern, the third worth thirty seconds. Adding on the first occurrence is how libraries fill with entries nobody uses again.
What not to put here
- Anything needing the cursor in the middle. A function template you have to land inside is an editor snippet.
- Anything with a variable.
Hi {name},cannot be filled in by a plain expander, and a snippet you edit after expansion is often slower than typing it. - Real secrets. No tokens, no keys, no passwords. Expansion is blocked in password fields and password managers by design, but a token in a snippet file is a token in a plaintext file on your disk, and it ends up in the export you send a colleague.
- Anything your editor already handles. Duplicating editor snippets system-wide gives you two sources of truth that drift.
Where it will not fire
- Elevated windows. An expander running as your user cannot send input to a process running as administrator. If you keep an admin PowerShell open, expansion is dead in it unless the expander is elevated too.
- Remote sessions and virtual machines. Your keystrokes are being forwarded to another machine; the expander is on this one. Install it where the text lands.
- Password fields and password managers. By design, with no override.
- Some terminals in some modes, and applications that draw their own text and expose nothing to Windows.
That boundary is a reason to keep the editor layer rather than trying to replace it.
Sharing a set with the team
Export to JSON or CSV and keep the file in the repository: the on-call sentence, the deploy announcement, the internal URLs, the review prefixes. Everyone imports it, and because import does not silently overwrite an existing shortcut, people keep their personal entries and gain the shared ones. Prefixing shared triggers distinctly, ;t- for team say, makes it obvious later which came from where.
Frequently asked questions
Should I use this instead of my editor's snippets?
How is this different from shell aliases?
Can a snippet include today's date?
{date}, {time} and {datetime} resolve at the moment of insertion, with custom formats like {date:yyyy-MM-dd}.