FAQ
- Why install Elm tools using
elm-tooling
instead ofnpm
? - When should I use
elm-tooling
to install tools? - How does
elm-tooling install
work? - Who uses
elm-tooling
? - Is
elm-tooling
stable? - 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-review
supported? - Why does
elm-tooling
put stuff innode_modules/.bin/
? - What does
elm-tooling
put innode_modules/.bin/
? - Is running stuff with
npx
slow? - Is
elm-tooling
forever locked into the npm ecosystem? - What’s the point of having
elm-json
inelm-tooling.json
? - Why not put stuff in
elm.json
instead? - How do I use a proxy?
Why install Elm tools using elm-tooling
instead of npm
?
Installing elm
, elm-format
and elm-json
using npm
(version 7) and elm-tooling
:
Metric | npm | elm-tooling |
---|---|---|
Number of packages | 65 | 1 |
node_modules/ size | 40 MiB | 116 KiB |
Installation time | 8 s | 2.5 s |
Re-installation time | 1.6 s | 1.5 s |
Download verification | None | SHA256 |
Comments:
-
Number of packages: Why are 65 npm packages installed just to get
elm
,elm-format
andelm-json
onto my computer? -
node_modules/
size: How canelm-tooling
be so much smaller?- Some of the 65 npm packages are pretty heavy.
elm-tooling
has no dependencies, and instead uses thecurl
(orwget
) andtar
that come with basically all operating systems (even Windows!) out of the box. elm-tooling
puts the executables in a central location (~/.elm/elm-tooling
) instead of in the localnode_modules/
folder.
(Measured on macOS; executables vary slightly in size between macOS, Linux and Windows (also disk block size).)
- Some of the 65 npm packages are pretty heavy.
-
Installation and re-installation time: This of course depends on your Internet speed, and also on npm cache.
npm
used to be much slower, but has stepped up their game. Either way, withelm-tooling
you get the other benefits mentioned here (fewer dependencies and improved security) besides good performance. (Note that re-installation time forelm-tooling
includes re-installingelm-tooling
itself withnpm
. That’s where most time is spent, whileelm-tooling install
is basically a no-op when the executables already exist in~/.elm/elm-tooling
.) -
Download verification: Security.
elm-tooling
ships with SHA256 hashes for all tools it knows about and verifies that download files match.elm-tooling
itself is hashed in yourpackage-lock.json
(which you commit). Theelm
,elm-format
andelm-json
npm packages on the other hand download stuff without verifying what they got.
Finally, the elm
, elm-format
and elm-json
npm packages are essentially hacks. The elm
npm package for instance does not contain Elm at all. It just contains some code that downloads Elm using a postinstall script (or at the first run).
When should I use elm-tooling
to install tools?
In short: For the same reasons you’d install tools using npm
.
If you’re just starting out, don’t forget to check out the official documentation as well:
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 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.
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.json
part of yournpm
package.elm-tooling.json
is 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.json
up 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
,wget
or Node.js’https
module. -
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
tar
or Node.js’zlib
module (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
.)
-
Who uses elm-tooling
?
elm-test and elm-review both use elm-tooling
to install elm-json.
The elm-pages-starter template uses elm-tooling.json
and elm-tooling
to install elm
and elm-format
.
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. There are no planned features, other than adding support for new tools and versions as they come, and adding validation for new fields in elm-tooling.json
as they are invented.
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.
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-tooling
itself from a project, runnpm uninstall elm-tooling
inside it. -
To remove downloaded executables, remove the directory where
elm-tooling
puts 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:
asdf
supports macOS and Linux, whileelm-tooling
also supports Windows.asdf
does not verify what it downloaded, whileelm-tooling
uses SHA256 to check downloads.asdf
requires collaborators to useasdf
as well (or figure out themselves how to get the correct versions of all tools), whileelm-tooling
only requires Node.js andnpm
which 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 a ~200 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-test and elm-review both use 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.