Skip to main content

Stop Arguing With Your Terminal About Python Versions

· 4 min read
Danish Javed
Software Engineer

Project setup should be boring. Not in a "this is beneath me" way — in a "this takes thirty seconds and I never think about it" way.

Most of the time, it isn't.

You clone a repo you haven't touched in six months. The README says "install Python 3.11". You have 3.12. Something breaks. You remember there's a .python-version file somewhere, or maybe a requires-python in pyproject.toml. You spend twenty minutes figuring out which version manager you're even supposed to be using for this project before you've written a single line of code.

This isn't a Python problem. Terraform has tfenv. Node has nvm or volta or .nvmrc. Every language brings its own version manager, its own config file format, its own way of silently using the wrong version. And that's before you even get to figuring out how to run things — is it make test? ./scripts/test.sh? Some npm script buried in a package.json? Nobody knows. You ask Slack.

I got tired of this and started using mise. It's a single tool that handles both problems: pinned runtimes and discoverable tasks, for any language, in one file.

A Python service looks like this:

[tools]
python = "3.12.3"

[tasks.test]
description = "Run the test suite"
run = "pytest"

[tasks.verify]
description = "Run all checks before pushing"
depends = ["test", "build"]

Run mise install and you get exactly that Python version. Run mise tasks and you see everything the project knows how to do. Run mise run verify before pushing. That's it.

The part I find most satisfying is that mise run <task> becomes a stable interface that hides whatever's behind it. I had a project that needed a custom k6 binary with SSE support for load testing a streaming API. Building it requires Go and a tool called xk6, which most people have never heard of. With mise, that's just:

[tools]
go = "1.22.3"

[tasks.build]
description = "Build k6 with xk6-sse extension"
run = "xk6 build --with github.com/phymbert/xk6-sse"

Now mise run build works for everyone — the developer who knows what xk6 is, the one who doesn't, and the CI job. Nobody has to know what's behind it. When I added another extension later, I changed one line. The interface didn't move.

Speaking of CI — this is where the real payoff is. A GitHub Actions workflow for a mise project looks like:

jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: jdx/mise-action@v2
- run: mise run verify

mise-action reads mise.toml, installs the pinned versions, and puts them on PATH. Then mise run verify runs the exact same thing you run locally. No separate version install steps. No drift between what CI checks and what you check. This is the thing that makes it worth the setup cost — CI and local are no longer two separate mental models.

The one thing mise can't do is install itself. You need it on the machine before any of this works. I solve that with Chezmoi, a dotfile manager that runs once on a fresh machine. A run_once_install-mise.sh script does the bootstrap:

#!/bin/sh
curl https://mise.run | sh

Then the shell hook in ~/.zshrc (also managed by Chezmoi) activates mise per directory:

eval "$(mise activate zsh)"

Chezmoi sets up the machine, mise sets up each project. Neither knows the other exists. You go from a blank laptop to a running project without reading a setup guide — which is the point.

It won't fix an undocumented deployment process or a service that can't run locally. It encodes what's already known. And if your team is already settled on nvm + make for a single-language, single-runtime project, the migration cost might not be worth it. The value really compounds when you're working across multiple projects or switching between them regularly — which, in my experience, is most of the time.


mise replaces pyenv, nvm, rbenv, tfenv, asdf, and most other per-language version managers. If you're on asdf already, migration is painless — mise reads .tool-versions files natively.

Vscode Snippet To Add Markdown Frontmatter

· One min read
  1. Click on settings for VSCode
  2. Click on "User Snippets
  3. Click on "New Global Snippets File..."
  4. Add the following JSON which will be limited to markdown files only
{
"Add Docusaurus blog frontmatter": {
"body": [
"---",
"draft: true",
"modified: ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}T${CURRENT_HOUR}:${CURRENT_MINUTE}:${CURRENT_SECOND}.000Z",
"date: ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}T${CURRENT_HOUR}:${CURRENT_MINUTE}:${CURRENT_SECOND}.000Z",
"title: ${TM_FILENAME_BASE/(\\w.*)/${1:/capitalized}/}",
"slug: ${TM_FILENAME_BASE/([\\w-]+$)|([\\w-]+)|([-\\s]+)|([^\\w]+)/${1:/downcase}${2:/downcase}${2:+-}/gm}",
"---"
],
"description": "Create Blogpost Frontmatter",
"scope": "markdown,mdx,md",
"prefix": ["blog", "draft blog", "frontmatter", "add frontmatter"]
}
}

Establishing A Walking Skeleton For Projects

· 2 min read

I've been reading the excellent book Growing Object-Oriented Software, Guided By Tests and there's so much that resonated with me about starting work on a new project.

As with anything new, give developers some shiny new something to work on and there's always the temptation to dive right in and get started with code. This often means that you're starting from the inside-out of a problem space and often some operational details are overlooked. When we're done solving that problem, trying to release that or to push that to production is often a problem nobody had perceived.

I recently experienced this on a project where we'd resorted to creating the application locally to put that online later. We had an idea of things like tech limitations and choices at the time, and deferring that decision seemed right, but it later came to bite us when we wanted to release the first feature.

We had roadblocks after one another, these came in the form of security policies, technology choices and release process already in place and trying something new. This whole thing cost us a couple of months of back and forth between dev/ops/admin folks.

So if I could tell my past self, I would say, release early and release often even if it means releasing the project skeleton in a hello world state.

In the context of the book I've been reading, establishing a walking skeleton is hugely important.

Journey To The Centre Of The Stack

· 6 min read

Dockerising the legacy

Making changes to application infrastructure can be daunting at the best of times so when it was decided that we move to the world of containers, I took on a task I didn’t know the depth of, so I am going to share my experience of getting my hands dirty.

At the time, I was new to docker but very interested in the technology, as technology folks, we all love a shiny new toy to play with. Apart from that the advantages and thus the reasons for so are listed as follows in no particular order:

  • Introducing speedier changes and testing ideas faster
  • Infrastructure as code
  • Simplify application/tech stack
  • Be cloud-friendly

JSON Web Tokens

· 6 min read

What is it?

JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.

JSON Web Tokens are an open, industry-standard RFC 7519 method for representing claims securely between two parties. See here: https://jwt.io

Blogging Like a Hacker

· One min read

Hello World 🌏

This is my first post, hoping there's a lot more I can write, but for now, this is me getting started with blogging.

I am an experienced Software Developer from the UK. I started my first fulltime job in 2011, I never thought to share my thoughts & experience. Through this blog, I am hoping to channel my thoughts and hopefully pay forward the knowledge in the same way I've found to be useful from other bloggers.

For now, I have a lot to learn about GitHub pages but I shall be adding more content over the coming future.

Stay tuned. ⚠️ 🚧