FAQ
- Comparison with the
elmand@lydell/elmnpm packages - Comparison with the
elm-format,elm-jsonandelm-test-rsnpm packages - Why should I use
elm-toolingto install tools? - How does
elm-tooling installwork? - Is
elm-toolingstable? - Can I install the tools globally?
- How do I uninstall?
- What’s the difference compared to
asdf? - Which tools are supported?
- Are Node.js based tools such as
elm-reviewsupported? - Why does
elm-toolingput stuff innode_modules/.bin/? - What does
elm-toolingput innode_modules/.bin/? - Is running stuff with
npxslow? - Is
elm-toolingforever locked into the npm ecosystem? - What’s the point of having
elm-jsoninelm-tooling.json? - Why not put stuff in
elm.jsoninstead? - How do I use a proxy?
Comparison with the elm and @lydell/elm npm packages
The official
elmnpm package used to have a lot of heavy dependencies and no verification of the downloaded binaries, but that has been fixed since version 0.19.1-6 of theelmnpm package, which is amazing! This makes the below comparisons seem a bit silly.
| Metric | elm npm package (>=0.19.1-6) | @lydell/elm npm package | elm-tooling |
|---|---|---|---|
| Number of packages | 2 | 2 | 1 |
| extra npm package metadata requests | 4 (one for every supported platform) | 6 (one for every supported platform) | 0 (no dependencies) |
| npm deprecation warnings | 0 | 0 | 0 |
node_modules/ size, not counting binaries | 32 KiB | 32 KiB | 124 KiB |
| Installation time | 3 s | 3 s | 2 s |
| Re-installation time | 0.5 s | 0.5 s | 0.3 s |
| Download verification | SHA512 | SHA512 | SHA256 |
| Supports macOS ARM | Yes | Yes | Yes |
| Supports Linux ARM | No | Yes | Yes |
| Binary location, npm | Every node_modules/ | Every node_modules/ | Once in ~/.elm/elm-tooling/ |
| Binary location, pnpm | Once in a shared location | Once in a shared location | Once in ~/.elm/elm-tooling/ |
In other words, compared to the official elm npm package and the unofficial @lydell/elm npm package, elm-tooling offers:
- More binaries than
elm. The same binaries as@lydell/elm. - No duplication of the binary in every project. But that’s up to which package manager you use. pnpm gives the same effect.
- Faster installation in theory, but in practice no difference.
- Faster execution on Windows. npm packages have to use a Node.js wrapper around binaries on Windows, which adds ~100 ms startup time.
elm-toolinguses a.cmdfile which executes instantly. - Faster execution when using Yarn 2+ (Berry). Yarn 2+ requires a Node.js wrapper around binaries, which adds ~100 ms startup time.
elm-toolinguses a symlink or.cmdfile which executes instantly. - So in summary: Not much.
elm-toolingeven has a potential downside: There are mirrors for npmjs.com, whileelm-toolingalways downloads from github.com.
Comparison with the elm-format, elm-json and elm-test-rs npm packages
- elm-format: Version 0.8.6 and later use the
@lydell/elmapproach! 🎉 - elm-json: Similar to
elm, but more dependencies (65, 6.4 MiB). 👉 Pull request for switching to the@lydell/elmapproach - elm-test-rs: Uses the
@lydell/elmapproach! 🎉
Why should I use elm-tooling to install tools?
In short: For the same reasons you’d install tools using npm.
If you’re just getting started, install Elm whatever way you think is the easiest so you can get started coding. Installing Elm globally using the official installer can be a great way. But if you’re already familiar with installing stuff with npm it might be just as easy to start with elm-tooling. It doesn’t really matter. You can always change the installation method later.
Don’t forget to check out the official documentation as well:
For Elm applications
When a new Elm version comes out, your old projects will continue to work since they have a fixed local Elm version. Now, new Elm versions aren’t released very often so it’s not a super big deal, but when a new version does come out it’s nice not having to upgrade each and every project at the same time.
elm-format releases a little bit often than Elm, and even with a patch release there can be tiny formatting changes. You wouldn’t want two contributors using different elm-format versions and format files back and forth all the time.
For Elm packages
For the same reasons as for Elm applications. Make it easy for contributors to get the correct versions of all tools.
For Elm tools
Have you written an Elm related tool in Node.js? If your tool calls for example elm, elm-format or elm-json you’re gonna need those tools locally for development, as well as in CI. You can use elm-tooling.json and elm-tooling install for this purpose.
Note:
- Don’t make
elm-tooling.jsonpart of yournpmpackage.elm-tooling.jsonis only for development and CI, not for production code. Use the getExecutable API if you need to depend on some other tool. - Use
"prepare": "elm-tooling install"instead of"postinstall": "elm-tooling install". See Quirks.
How does elm-tooling install work?
In elm-tooling.json you can specify your tools:
{
"tools": {
"elm": "0.19.1",
"elm-format": "0.8.4"
}
}
elm-tooling install downloads the tools you’ve specified to “Elm home” (if they don’t exist already). After using elm-tooling in a couple of projects you might end up with something like this:
~/.elm/elm-tooling
├── elm
│ └── 0.19.1
│ └── elm
├── elm-format
│ ├── 0.8.3
│ │ └── elm-format
│ └── 0.8.4
│ └── elm-format
└── elm-json
└── 0.2.8
└── elm-json
elm-tooling install then creates links in your local ./node_modules/.bin/ folder:
./node_modules/.bin/elm -> ~/.elm/elm-tooling/elm/0.19.1/elm
./node_modules/.bin/elm-format -> ~/.elm/elm-tooling/elm-format/0.8.4/elm-format
The algorithm is roughly:
-
Find an
elm-tooling.jsonup the directory tree. -
For every tool/version pair in
"tools":-
Look it up in the built-in list of known tools, to get the URL to download from and the expected number of bytes and SHA256 hash.
-
Unless the executable already exists on disk in
~/.elm/:-
Download the URL using
curl,wgetor Node.js’httpsmodule. -
Verify that the downloaded contents has the expected number of bytes.
-
Verify that the downloaded contents has the expected SHA256 hash.
-
Extract the executable using
taror Node.js’zlibmodule (gunzip). -
Make sure the extracted file is executable (
chmod +x).
-
-
Create a link in
./node_modules/.bin/. (Thenode_modules/folder is always located next to yourelm-tooling.json.)
-
Is elm-tooling stable?
Yes! It’s tested on macOS, Linux and Windows, and has great test coverage. It’s written in strict TypeScript, and focuses on handling errors at all points.
Can I install the tools globally?
There’s no global elm-tooling.json. Only local, per-project ones.
As long as you define the needed tools in every project, you don’t really need global installations. Use npx elm and npx elm-format etc. A benefit of not having global installations is that you can never run the global version instead of the project version by mistake.
If you want a global elm command you could try the official installer, the elm npm package or brew.
On macOS and Linux, you could alternatively add symlinks in your $PATH. For example, on macOS:
ln -s ~/.elm/elm-tooling/elm/0.19.1/elm /usr/local/bin/elm
Another approach would be to create a “project” somewhere, and put its ./node_modules/.bin/ in $PATH. For example, you could add ~/my-global-elm-tooling/node_modules/.bin/. Beware that ./node_modules/.bin/ might contain more things than just elm and elm-format etc, depending on what npm packages you (indirectly) install.
How do I uninstall?
-
To remove
elm-toolingitself from a project, runnpm uninstall elm-toolinginside it. -
To remove downloaded executables, remove the directory where
elm-toolingputs them. The default locations are:- macOS and Linux:
~/.elm/elm-tooling/ - Windows:
%APPDATA%\elm(for example,C:\Users\John\AppData\Roaming\elm\elm-tooling)
If you’d like to remove just one executable, here are some example paths to look at:
- macOS and Linux:
~/.elm/elm-tooling/elm/0.19.1/elm - Windows:
C:\Users\John\AppData\Roaming\elm\elm-tooling\elm\0.19.1\elm.exe
- macOS and Linux:
What’s the difference compared to asdf?
The asdf version manager has support for Elm and elm-format. Here are some differences:
asdfsupports macOS and Linux, whileelm-toolingalso supports Windows.asdfdoes not verify what it downloaded, whileelm-toolinguses SHA256 to check downloads.asdfrequires collaborators to useasdfas well (or figure out themselves how to get the correct versions of all tools), whileelm-toolingonly requires Node.js andnpmwhich are more commonly installed.
Which tools are supported?
Since Elm tools are so few and update so infrequently, elm-tooling can go with a very simple and reliable approach: Supported tool names, versions and SHA256 are hard coded – see KnownTools.ts.
Open an issue or pull request if you’d like to see support for another tool or version!
Will elm-tooling outgrow this approach some day? Yeah, maybe. But until then – KISS!
Only supporting Elm tooling rather than trying to be a generalized installation tool allows elm-tooling to be much simpler and laser focused on making the Elm experience as good as possible.
Are Node.js based tools such as elm-review supported?
The CLI for elm-review is written in Node.js and uses other npm packages. You can’t beat npm (or other Node.js package managers) when it comes to installing npm packages.
So Node.js based tools are not supported. Only tools that are distributed as platform specific executables are.
Why does elm-tooling put stuff in node_modules/.bin/?
Installing stuff into the local node_modules/.bin/ folder might sound strange at first, but piggy-backing on the well-supported npm ecosystem is currently the best way of doing things. This lets you use the tools field of elm-tooling.json without your editor and build tools having to support it.
What does elm-tooling put in node_modules/.bin/?
On macOS and Linux, node_modules/.bin/ only contains symlinks. These symlinks point to executable files. The executables don’t even need to invoke Node.js! So elm-tooling install simply puts symlinks in node_modules/.bin/ too. For example, node_modules/.bin/elm could point to ~/.elm/elm-tooling/elm/0.19.1/elm.
On Windows, npm creates three shell scripts (cmd, PowerShell and sh) per executable in node_modules/.bin/, in lieu of symlinks. elm-tooling install mimics these shell scripts, but they are much simpler. All they need to do is invoke an executable in %APPDATA%\elm, passing along all arguments.
Is running stuff with npx slow?
npx is written in Node.js. All Node.js tools have at least ~100 ms startup cost. Other than that there’s no difference.
Is elm-tooling forever locked into the npm ecosystem?
No!
The elm-tooling CLI could be written in something other than Node.js.
Instead of using for example npx elm to run tools, we could have elm-tooling run elm. elm-tooling run would read elm-tooling.json to find which version of the tool to use, and also add any other tools in elm-tooling.json to $PATH for the execution. This way tools can do stuff like spawn("elm") and get the correct version as if it was installed globally.
IDE:s and editors would have to support elm-tooling.json somehow, too, though, instead of looking for executables in ./node_modules/.bin/. I’m sure we would find a solution there, but for the time being it’s much easier for elm-tooling to mimic the npm stuff so things just work.
What’s the point of having elm-json in elm-tooling.json?
elm-review uses elm-tooling to install elm-json.
By having elm-json in elm-tooling.json you can download all executables in parallel in one go.
For people who aren’t Elm experts, it’s nice to have elm-json available for all contributors. It’s often easier to install Elm packages using elm-json than elm install.
Why not put stuff in elm.json instead?
elm has a tendency to remove keys it does not recognize whenever it updates elm.json.
How do I use a proxy?
elm-tooling uses curl to download stuff if it exists, otherwise wget, and finally the https Node.js core module. So if you need to do any proxy stuff or something like that, you do that via the environment variables and config files that curl and wget understand. For example, curl proxy environment variables. Most systems – even Windows! – come with either curl or wget.
This also applies to any npm package that under the hood uses elm-tooling to install something.