~/sd
is my s
cript d
irectory. It looks like this:
$ tree ~/sd
/Users/ian/sd
├── blog
│ ├── preview
│ └── publish
├── book
│ ├── open
│ ├── pdf
│ ├── progress
│ └── typeset
├── cat
├── dim
│ └── visualize
├── edit
├── git
│ └── ugh
├── help
├── new
├── nix
│ ├── diff
│ ├── info
│ └── sync
├── tmux
│ ├── init
│ └── restore
└── which
sd
is a command on my PATH
. It dispatches its arguments to my script directory.
$ sd blog publish
Will run the script ~/sd/blog/publish
.
This sounds like a dumb way to save myself having to type a few characters. Which it is. But it’s also slightly more than that:
sd
has nice tab completion. That’s the only real difference between sd
and ~/sd
: those little descriptions of what the commands do. In case you don’t run JavaScript, it looks something like this:
$ sd nix <TAB>
diff -- prints what will happen if you run sync
info -- <package> prints package description
sync -- make user environment match ~/dotfiles/user.nix
It’s not much. But it’s nice.
Those descriptions come from comments in the command files themselves, or from separate command.help
files (in case there is a lot to say, or the command is not a shell script).
For example, in the demo above, I run sd help nix sync
, which ends up running cat ~/sd/nix/sync.help
. The first line is all that ends up in the completion menu, but the rest of the text is there in case I forget how a command works.
a boring story about sd
I wrote sd
one afternoon when I couldn’t find a script I wanted in my ~/bin
. I knew it was there – and I knew what it did – but I couldn’t remember what I’d named it.
I had close to a hundred different scripts in ~/bin
, all with names that made perfect sense when I added them: visualize
, transplant
, deploy
, etc.
I decided enough was enough, so I added a little structure, and sd
was born.
It’s much easier to remember what commands do when they’re namespaced like this. And it’s much easier to remember how to use them when you write their usage down. I’ve used sd
ever since, and I don’t think I could go back to a flat ~/bin
.
I only have a few sd
commands on my laptop, because I don’t find myself writing a lot of complicated scripts at home. But sd
was written for work, where I had dozens of helpers all neatly categorized by project or tool or domain. It was good.
do you want to use sd
?
It’s not really a thing. It’s more of an idea. You can implement it yourself in one sitting, if you want.
But of course you don’t want to figure out how to write your own shell completion. Shell completion is some arcane nonsense. You want me to have already done it. But here’s the thing: I only wrote zsh
completions because I only ever use zsh
interactively.
I’ve sometimes thought about rewriting sd
as something other than a pile of shell and publishing it and publicizing it and adding bash
support and what have you. But you know what? I probably won’t ever do that. But maybe someone else will, if they like the idea enough.
You’re welcome to use my implementation, though, if you use zsh
. It works on macOS and Linux. It lives in my dotfiles repo its own repo because I want it on every machine I use and I’m very lazy a responsible adult. See also bin/completions/_sd
and sd-common/
. sd-common
are the scripts like which
and cat
that must exist in ~/sd
or something will probably break (I install them as symlinks to my dotfiles repo).
If you want completions to work, you have to add this in your .zshrc
file:
fpath=(~/bin/completions $fpath)
Where ~/bin/completions
is wherever you end up putting the _sd
script.
One last note: sd
only looks for executables, so you can add non-executable helpers that you can source
from multiple scripts in the same directory. When sd
invokes a command, $0
is the absolute path to the command, so you can use dirname "$0"
to get at your helpers. Like you’d expect.
how has sd
affected you
Being able to type sd new foo command
instead of vim ~/bin/command
, typing the shebang, trying to run it, realizing I forgot to make it executable, running it again… it’s made my life slightly better. And because it’s so easy to save snippets for later, I find that I’m much more likely to do it – and a lot less likely to find myself combing through ctrl-r
a few months later.
Otherwise, you know, it’s not lifechanging. It won’t help you to appreciate the smaller beauties all around you. You’ll still wake up feeling groggy. Lately I’ve been using it to make user-friendly wrappers around nix-env
as part of my series How to Learn Nix, which has been nice.
what would you have done differently
Make(This is done.)sd new
support a--
escape argument and treat the rest of the arguments as the script, for easily stashing oneliners:sd new foo bar -- echo foobar
.Figure out how to share logic betweensd
and the autocomplete script_sd
. Lotta copy-paste right now.- Some nice way to generate command completion for command arguments, instead of just for commands themselves.
Especially for commands likesd cat
andsd edit
which are much harder to use than they should be. (I learned that bash actually doesn’t support the kind of autocomplete thatbash
support I guesssd
uses, so autocompletion would be far less useful in bash. Why are you using bash? who’s doing this to you)- In the case that
$0
is notsd
, treat it as part of the script path, so you can make very lightweight command wrappers that work without having to typesd
. Basicallyln -s $(which sd) ~/bin/some-command
, and then you can typesome-command foo
instead ofsd some-command foo
. (This might still be cool? But it sounds like a feature in search of a use case.) Support(done)sd foo bar --help
instead ofsd help foo bar
, because it’s slightly annoying to reposition your cursor. But that’s kind of a whole can of worms.- yes the real solution here is to not use shell and find some nice alternative that actually understands how command line arguments work but there really just isn’t you know it’s
20212022 and biden is president and bash is still the only thing we have don’t talk to me about oil shell i know all about oil shell
- yes the real solution here is to not use shell and find some nice alternative that actually understands how command line arguments work but there really just isn’t you know it’s
But sd
is like a 95/20 situation. It’s pretty good even in its neglected, janky state. As long as you’re using zsh
.