I did that for 10+ years and got fed up with having to remember which names I gave to my scripts that month. I gradually evolved my views and that got reflected with the names of the scripts.
`just` helped me finally move away from that. Now I have i.e. `just check` in projects in different languages that all do the same thing -- check types and/or run various linters. I can go in a directory and run `just check` and I know I have taken care to have all checks that I want in place. Similarly I can run `just test` and I know I'll have the test suite ran, again regardless of the programming language or framework.
Absolutely nothing wrong with a directory full of scripts but I lost patience for having to scan what each does and moved away from them.
How is that different from having a scripts dir, and a script called `check` or `test`?
How is `just -l` different to `ls scripts`?
And it was already said: if you like it more, use it. Nobody is holding a gun to your head. And I even explained that I used that in the past and moved away from it.
AFAICT, the productivity improvements you described came exclusively from using a consistent naming convention, not from Just. And since everyone's dev env supports subdirectories with shell scripts already, why not simply use that instead of requiring Just?
Finally and additionally as a response: because it's also all in one place. I don't want 10+ scripts. For the third time: I used bespoke scripts and found them not good enough compared to Just, now for even more reasons clearly spelled out. Sigh.
10+ scripts with standard names ("clean", "test", "build", etc.) in a subdir added to $PATH seems to me to be easier to manage -- if the scripts are independent of each other. If they do have dependencies on each other, but the dependencies are "treelike" (meaning that for every target you might want to run, all of its transitive deps are reached via a unique path), it's still easier (than either make or Just) to have separate scripts, and turn each dep into a plain invocation at the top of each script. It's only when that approach starts to invoke deps multiple times (because it has become non-treelike) that either make or Just starts to offer an advantage.
I think if you look at this with clear eyes, you'll see that 100% of the value you feel you're getting from Just is actually coming from the naming convention that Just nudged you towards.
And I have not touched your comment btw. I rarely downvote these days and I have to be really pissed to do so. I was not pissed earlier, more like a little frustrated as you seemed to ask without reading, as if demanding a complete answer without willing to piece together the info given in several other comments.
So... you were talking about global scripts. I was not. I was talking about per-project directory with scripts because very often projects have their little quirks that make all their scripts frustratingly 99% identical but never 100%. I danced this tango dozens of times -- not exaggerating, I am a contractor (though I hope to finally stop, currently looking for a proper long-term job with good culture fit) and worked on many projects -- and ultimately got extremely frustrated.
At one point I did attempt to make those universal scripts you speak of. The even more maddening thing is that they worked for part of the projects... and didn't work for others. It was a rough 60/40 split. So you end up maintaining even more of them. So I gave up.
Very soon before that I found `just` and very quickly recognized the benefits: project-local commands / scripts, centralized location (just one file), ability to delegate to parent Justfile (i.e. you can have a dedicated folder for Golang projects and that one can contain a Justfile with e.g. `just lint` task that calls `go vet` and `staticcheck` etc., without having to copy-paste that into every Golang project Justfile file, though I actually prefer that nowadays -- better to have completely self-contained tooling after all but still, for super dev-specific stuff that does not belong in version control the parent Justfile workflow is quite a good fit), and a very easy syntax that still allows for doing stuff that will make you pull your hair out if you attempt them with pure sh or bash and if you haven't memorized their specifics over the course of a lifetime (which is something I attempted but gave up on because it was more or less memorization of exceptions of the exceptions).
Now, to address this:
> I also haven't seen in your previous response how Just is better than a subdir with shell scripts named according to a convention.
I am not impressed by conventions that are not enforced with a spiked club. Which means: we the people forget stuff easily. I suffered from that too. Conventions don't mean much when you misspell the script filename or put `-f` instead of `-e` in the `set` call at the top of the script. :)
I prefer loud failures and not silent mess-ups.
My position is informed by a lot of negative past experiences. Does not mean that my priorities are universal or unconditionally better. Not at all. It means that everything I got through in my career made me appreciate `just` and it was a near-perfect fit for my needs.
> I think if you look at this with clear eyes, you'll see that 100% of the value you feel you're getting from Just is actually coming from the naming convention that Just nudged you towards.
Sure, it encouraged me to finally settle on a naming convention but I've done this before as well. I still prefer the singular file approach + ability to delegate to parent files.
The less files in total the better. I have found this rule to make me more productive.
If you have gotten this far: nowhere did I claim objective improvements. I had discussions in the past (might have been in other `just` threads even!) with curmudgeons who loudly proclaimed "skill issue!" on my non-preference towards make's bash-isms and weird rules. So for them `make` + other scripts (even Perl / Python ones) are working just fine and the rest are "kids running after shiny toys".
I don't mind them thinking that. I have my motivation and, as said above, it's well-motivated given my past and my way of work and mental preferences.
Hope that helps.
And it sounds like Just is that tool for you! I'll probably keep using make, now that I've spent so much time wrestling with its many idiosyncrasies, but you never know.
> And I certainly agree that bash and make are absolutely Byzantine at this point -- footguns on footguns.
Yeah, that's my problem. Not like I don't have memory in my brain, not like I can't learn make and bash -- I did so several times almost from scratch but as I am not using them every day, the memories always fade. It's best to relearn something without footguns than one with. Hence I am using `just`. It's straightforward and very easy to catch up with even if you forget it. Not so with make and bash.
If you are very invested in them and are feeling at home with them, great for you -- I am not claiming unquestionable and countless benefits. I am claiming it works well for my brain and my workflow, and most of all -- the frequency with which I have to do scripting.
all:
@ls -1 tasks
% :: tasks/%
@./$<
And then fill my `tasks/` directory with individual executables.So he isn't the culprit.
Oh and I did not downvote him.
Aside from that, it has lots of built-in ergonomics like consistent argument parsing, functions to say what OS you’re on, an easy way to hide helper functions, the ability to execute a justfile in a great-grandparent directory, etc.
You can totally do any of those things with shell scripts. I prefer letting someone else invent all the bells and whistles there so I don’t have to.
My genuine advice is to download it and play with it for an hour. If you don’t like it, you’ve learned a little about a tool you’re bound to come across sometime. If you do like it, now you’ve added another tool to your palette. Either way you learn something useful.
There’s room for both. Neither replaces the other. But it turns out many of my projects need tools closer to Python/Just than Java/Make.
`./scripts/<tab>`
`./sc<tab><tab>`
(For those who haven't used it, fzf is a fuzzy-searchable menu for the command line. You pipe lines of input to it, and it shows them in a menu. You start typing and it fuzzy searches the menu and selects the best match. Then you press Enter to pipe that out, or Tab for multi-select. It's fantastic.)
I have convenience functions in my profile script that pipe different things to fzf...scripts, paths in the current directory to copy to the clipboard, etc. It's indispensable.
Bonus: progressive enhancement. If someone doesn't have fzf/those convenience functions, it's just a directory with shell scripts, so they don't have to do anything special to use them.
E.g: You have a docker container, you might be `run`ning it, `exec`ing it etc. from the same compose-file. So Just gives you the ability to link those shared commands within the same file. Once the entrypoints get too numerous you can either break them into scripts (I do this partially depending on the level of behavioral complexity in the script) or partition your justfiles and import them into a single master.
You can build complex recipes out of simpler ones. Sure, you could do that by creating a new shell script that calls other shell scripts, but then you're reinventing just.
You don't need to be in the directory to run those scripts.
I think a better question for you: What's the benefit of putting .PHONY recipes in Makefiles, when you could just have a directory full of shell scripts. If you find yourself using .PHONY recipes, then you already have a reason to use just.
Surely this is true for stuff in a ./bin or ./scripts folder - binaries, python with shebang etc?
https://just.systems/man/en/shebang-recipes.html
Which could be done in shell, but typically rather be limited to oneliners (invoking awk) rather than piping a heredoc to an interpreter.
There's already an easy way to solve this: $PATH.
> I think a better question for you: What's the benefit of putting .PHONY recipes in Makefiles, when you could just have a directory full of shell scripts. If you find yourself using .PHONY recipes, then you already have a reason to use just.
Well, I think it's the same question, rather than a better question. And the answer is yes, if all you need from make, now and in the future, is a set of .PHONY targets, then by all means just use shell scripts. make is used because often you need slightly more than this -- or you may do so tomorrow, and don't want to change the syntax you use to accomplish tasks.
I have 10 projects. Each with their own set of shell scripts. You want me (and all other developers) to pollute the $PATH with 10 directories?
And then you have a namespace problem. I usually have a "test" recipe in my justfiles. The analog would be a test.sh file. But with your solution, it will have to be projA-test.sh and projB-test.sh.
And if I dump them all into the $PATH, how do I quickly see the scripts relevant to a particular project?
2. This works only if you just happen to be in the directory above scripts.
I think it really has to be emphasized: One of the great things about just is that it works in Windows with no hassles.
I ask because cmd.exe has DOSKEY, which is basically a very slightly souped up version of bash's alias. I think it wouldn't be hard to use DOSKEY to replace CD and PUSHD with macros that run some command to update %PATH% and then change directory as usual.
just isn't something magical that will make scripts meant for Linux work in Windows, you know. Some people do actual development in Windows and have Windows scripts.
If you use git and don't need multiple "layers" of Justfiles (i.e., if you have all your scripts in a scripts folder at the top level of your repo), then in bash you can get what you want with:
run(){ `git rev-parse --show-toplevel`/scripts/$*; }
Now from any repo subdir, `run clean` will run a script named "clean" in the scripts folder at the top level.Likewise, if you are using make as a command runner and already know make well enough - by all means continue! In my experience, though, someone who doesn't know make will be much more likely to learn just than make.
I tend to sneak justfiles into the projects I work on. They usually don't have any good automation (no make, perhaps some scripts with a doc/md file explaining which script is for what). I sneak the justfile in the repository, and when it's mature, start showing teammates how I use it. They typically then switch to it. I don't think they would switch to it if it were a Makefile.
And all other features aside, it seems to be able to call commands from any subdirectory in a project, which is actually nice compared with a normal shell. I mean, you can replicate this with some lines of shellscripting, but not everyone seems to maintain an elaborated $BIN of personal tools.