I Was DEFINITELY Using The Wrong Dev Env CLI


I Was DEFINITELY Using The Wrong Dev Env CLI

This issue is brought to you by:

Teleport: Unified Identity Securing
Classic & AI Infrastructure

Teleport unifies identities — humans, machines, and AI — with strong identity implementation to speed up engineering, improve resiliency against identity-based attacks, and secure AI in production infrastructure.

I titled this newsletter like I did because I realized my old setup was a fragmented mess of five different tools when it could have been one.
I learned that managing runtimes, env vars, and task runners separately is not only a waste but also extremely hard when collaborating with others.
Mise (short for mise-en-place, which is a French culinary term for "everything in place") finally brings everything into one tiny, lightning-fast Rust binary that doesn't rely on the complexity of Nix.

Now, I'm fully aware that the last sentence might bring some heat, but, I already said my piece.

The best way to start is to stop using manual version managers and move your project settings into a single config file.
You can replace your messy Makefiles and complicated Docker setups for local development with a clean system that works the same way on your machine as it does in your CI pipeline (I'm not exaggerating, wait and read through).
By putting these learnings into action, you can automate your entire environment setup so that any new developer on your team can get started with just one command.
One command that runs a local dev env, pins versions, installs utilities, integrates scripts, reads secrets, loads variables, aaaaaand does everything, automatically. Right when you enter the project.


We have all been there when joining a new project.
You open the README and see a massive list of dependencies to install manually.
You have to hunt down specific versions of Node, set up local environment variables, and pray that your global Python version doesn't break the build.
It is a huge waste of time that turns a five-minute task into a three hour (if you're lucky) debugging session of your own terminal.
It feels like we are spending more time managing our tools than actually writing any code.

We usually reach for Docker and Nix

Most people try to solve this by reaching for heavy-duty tools like Docker or Nix.
They build giant containers to isolate everything or use things like Devbox (great option by any standard) to wrap around the complexity of the Nix ecosystem.
Others stick to the classic combination of a Makefile for scripts and Direnv for loading secret keys.
It feels like the professional way to do things because it is what everyone else is doing.
We just accept that the overhead is the price we pay for a working environment.

These tools often add more friction than they fix

The problem is that these solutions often come with their own hoops to jump through.

Docker is heavy and can feel sluggish for local development.
Not to mention having to mount a path, and having to `exec` in every time you need to make a change, and of course, not having your local shell with you.
Nix is incredibly powerful but has a steep learning curve that can give you Nix trauma when things go wrong (don't ask me how how I know).
Even great tools like Devbox still require you to have Nix installed in the background, which adds another layer of management you probably do not want.
If you're like me and use a hipster shell like Nushell, many of these tools don't even support you out of the box, leaving you to hack together your own configs.

Mise is the tiny Rust tool that does it all

Mise is a single tool written in Rust that handles your runtimes, your env vars, and your tasks all at once.
It is not a Nix wrapper, it is doing its own thing, which makes it incredibly fast and lightweight.
It has its own registry of tools, but it can also plug into other backends like homebrew, cargo, or even go.
It even includes a task system that is so robust it can function as your entire CI system.

To get started, you can install the tool using a simple curl command:

curl https://mise.run | sh

You can verify that everything is installed correctly and see your system architecture

mise version

If you want to run a specific tool version once without installing it, you can use the exec command

mise exec python@3.12 -- python

To pin a specific tool version to your current project, run:

mise use node@24

To make sure Mise automatically loads your tools and variables whenever you enter the directory, you need to activate it in your shell:

# not an actual command to run, but rather generating a script to $(eval)
mise activate

If you want a specific tool version to be available everywhere on your machine, you can set it globally:

mise use -g node@24

Mise allows you to define and run custom tasks that are stored in your project configuration:

# after setting a [task.build] in your toml file:
mise run build

If you forget what scripts are available in a project, you can list them all out easily:

mise tasks ls

You can even generate configurations for things like GitHub Actions or dev containers based on your Mise setup:

mise generate

Beyond just tools, Mise handles environment variables and integrates with secret managers like SOPS, age and even using fnox, and open source from the save author that can connect you to secret managers on cloud platforms or other options like 1Password and so on.

Your "works on my machine" excuses are officially over.

I hope this was valuable! Thank you for reading.

Feel free to reply directly with any question or feedback.

Have a great weekend!

ESPRESSO FRIDAYS

Every once in a while I send hand picked things I've learned. Kind of like your filter to the tech internet. No spam, I promise!

Read more from ESPRESSO FRIDAYS

I’m Done With Manual Proxies. (Use Traefik Instead) This issue is brought to you by: Incident.io: Move fast when you break things The all-in-one AI platform for on-call, incident response, and status pages—built for fast-moving teams. Get started for FREE! If you’ve ever felt like pulling your hair out while manually editing Nginx config files just to add one simple container, this is for you. Modern infrastructure is dynamic, but our proxies are often static. In the old days, you’d spin up a...

I replaced Docker with THIS. This issue is brought to you by: Graphite: The next generation of code review. Graphite is the AI code review platform where teams ship higher code, faster. Get started for FREE! You know why you’re here. Because reproducible environments make you tick but too much friction? makes you.. sick 🥁. After 12 years of containerizing / virtualenv-ing, I’ve finally found something that ticks all the boxes. I’m talking about throwing out npm, rvm, nix-env, virtualenv and...

Wait... NGINX can do WHAT?! This issue is brought to you by: Reliable DNS hosting & domain name managementWith DNSimple! From a streamlined interface to single-click integrations, DNSimple delivers the tools you need to simplify your day. Developers and system admins love our single-click integrations and automation tools for domains, DNS, and more. Enterprise teams simplify management of the most complex domain environments through our NEW Domain Control Plane. Try FREE for 30 days! Most...