{
    "archive_path": "archive/1751233099.942034",
    "base_url": "blog.vbang.dk/2025/06/29/tools-i-love-mise",
    "basename": "",
    "bookmarked_date": "2025-06-29 21:38",
    "canonical": {
        "archive_org_path": "https://web.archive.org/web/blog.vbang.dk/2025/06/29/tools-i-love-mise",
        "dom_path": "output.html",
        "favicon_path": "favicon.ico",
        "git_path": "git/",
        "google_favicon_path": "https://www.google.com/s2/favicons?domain=blog.vbang.dk",
        "headers_path": "headers.json",
        "htmltotext_path": "htmltotext.txt",
        "index_path": "index.html",
        "media_path": "media/",
        "mercury_path": "mercury/content.html",
        "pdf_path": "output.pdf",
        "readability_path": "readability/content.html",
        "screenshot_path": "screenshot.png",
        "singlefile_path": "singlefile.html",
        "warc_path": "warc/",
        "wget_path": null
    },
    "domain": "blog.vbang.dk",
    "downloaded_at": "2025-06-29T21:38:21.667880+00:00",
    "downloaded_datestr": "2025-06-29 21:38",
    "extension": "",
    "hash": "109SN3TRR9EKESBPNZ7F",
    "history": {
        "archive_org": [
            {
                "cmd": [
                    "/usr/bin/curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--proxy",
                    "socks5://tor-socks-proxy:9150",
                    "--head",
                    "--max-time",
                    "60",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 ArchiveBox/{VERSION} (+https://github.com/ArchiveBox/ArchiveBox/)",
                    "https://web.archive.org/save/https://blog.vbang.dk/2025/06/29/tools-i-love-mise/"
                ],
                "cmd_version": "8.10.1",
                "end_ts": "2025-06-29T21:39:10.016058+00:00",
                "index_texts": null,
                "output": "ArchiveError: Failed to find \"content-location\" URL header in Archive.org response.",
                "pwd": "/data/archive/1751233099.942034",
                "schema": "ArchiveResult",
                "start_ts": "2025-06-29T21:39:07.841964+00:00",
                "status": "failed"
            }
        ],
        "dom": [
            {
                "cmd": [
                    "/usr/bin/chromium-browser",
                    "--proxy-server=socks5://tor-socks-proxy:9150",
                    "--disable-features=DarkMode",
                    "--run-all-compositor-stages-before-draw",
                    "--hide-scrollbars",
                    "--autoplay-policy=no-user-gesture-required",
                    "--no-first-run",
                    "--use-fake-ui-for-media-stream",
                    "--use-fake-device-for-media-stream",
                    "--simulate-outdated-no-au='Tue, 31 Dec 2099 23:59:59 GMT'",
                    "--headless=new",
                    "--no-sandbox",
                    "--no-zygote",
                    "--disable-dev-shm-usage",
                    "--disable-software-rasterizer",
                    "--disable-sync",
                    "--window-size=1440,2000",
                    "--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 ArchiveBox/{VERSION} (+https://github.com/ArchiveBox/ArchiveBox/)",
                    "--user-data-dir=/data/personas/Default/chrome_profile",
                    "--profile-directory=Default",
                    "--dump-dom",
                    "https://blog.vbang.dk/2025/06/29/tools-i-love-mise/"
                ],
                "cmd_version": "131.0.6778",
                "end_ts": "2025-06-29T21:38:42.399925+00:00",
                "index_texts": null,
                "output": "output.html",
                "pwd": "/data/archive/1751233099.942034",
                "schema": "ArchiveResult",
                "start_ts": "2025-06-29T21:38:30.232557+00:00",
                "status": "succeeded"
            }
        ],
        "favicon": [
            {
                "cmd": [
                    "/usr/bin/curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--proxy",
                    "socks5://tor-socks-proxy:9150",
                    "--max-time",
                    "60",
                    "--output",
                    "favicon.ico",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 ArchiveBox/{VERSION} (+https://github.com/ArchiveBox/ArchiveBox/)",
                    "https://www.google.com/s2/favicons?domain=blog.vbang.dk"
                ],
                "cmd_version": "8.10.1",
                "end_ts": "2025-06-29T21:38:25.540274+00:00",
                "index_texts": null,
                "output": "favicon.ico",
                "pwd": "/data/archive/1751233099.942034",
                "schema": "ArchiveResult",
                "start_ts": "2025-06-29T21:38:22.155660+00:00",
                "status": "succeeded"
            }
        ],
        "git": [],
        "headers": [
            {
                "cmd": [
                    "/usr/bin/curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--proxy",
                    "socks5://tor-socks-proxy:9150",
                    "--head",
                    "--max-time",
                    "60",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 ArchiveBox/{VERSION} (+https://github.com/ArchiveBox/ArchiveBox/)",
                    "https://blog.vbang.dk/2025/06/29/tools-i-love-mise/"
                ],
                "cmd_version": "8.10.1",
                "end_ts": "2025-06-29T21:38:25.725688+00:00",
                "index_texts": null,
                "output": "headers.json",
                "pwd": "/data/archive/1751233099.942034",
                "schema": "ArchiveResult",
                "start_ts": "2025-06-29T21:38:25.570016+00:00",
                "status": "succeeded"
            }
        ],
        "htmltotext": [
            {
                "cmd": [
                    "(internal) archivebox.extractors.htmltotext",
                    "./{singlefile,dom}.html"
                ],
                "cmd_version": "0.8.5rc51",
                "end_ts": "2025-06-29T21:38:59.965960+00:00",
                "index_texts": [
                    "Tools I love: mise(-en-place) (https://blog.vbang.dk/2025/06/29/tools-i-love-mise/) (Michael Bang) (https://blog.vbang.dk/feed.xml) (/static/style.css)  (/) Michael Bang's blog (/feed.xml) RSS (/about.html) About (https://x.com/micvbang) (Twitter) \ud835\udd4f (https://bsky.app/profile/micvbang.bsky.social) (Bluesky) \ud83e\udd8b (https://www.linkedin.com/in/micvbang/) (LinkedIn) in     29 Jun 2025 Tools I love: mise(-en-place) (/tag/tools/) tools (/tag/cli/) cli (/tag/mise/) mise  Once in a while you get introduced to a tool that instantly changes the way you work. For me, (https://github.com/jdx/mise) mise is one of those tools. mise is the logical conclusion to a lot of the meta-tooling that exists around language-specific version and package managers like (https://asdf-vm.com/) asdf , (https://github.com/nvm-sh/nvm) nvm , (https://docs.astral.sh/uv/) uv , (https://github.com/pyenv/pyenv) pyenv etc. It makes it exceptionally easy to install, use, and manage software. It also allows you to manage (https://mise.jdx.dev/environments/) environment variables and (https://mise.jdx.dev/tasks/) declare tasks (run commands). Trying out new tools The first step in getting an intuitive understanding of what mise can help you with is to use it to install a tool. Pick your favorite and try it out; it supports (https://mise.jdx.dev/registry.html) a lot  ! I recently read about jj in (https://registerspill.thorstenball.com/) Thorsten Ball\u2019s newsletter and decided to try it out (again). I crossed my fingers and hoped that jj was (https://mise.jdx.dev/registry.html) one of the tools supported by mise and, to my delight, it was! The process looked something like this: $  jj\ncommand_not_found_handler:5: command  not found: jj $  mise use jj\nmise ~/projects/examples_mise/mise.toml tools: jj@0.30.0 $  jj version\njj 0.30.0 $  cd .. $  jj version\ncommand_not_found_handler:5: command  not found: jj $  cd  eaxmples_mise $  jj version\njj 0.30.0     As the above shows, with mise we\u2019re just one command away from installing and trying out a new tool, e.g. mise use jj . In the above we that mise printed mise ~/projects/examples_mise/mise.toml tools: jj@0.30.0 . This tells us that mise has created (or updated) the mise configuration on that path . We also see that if we cd out of ~/projects , the jj command is no longer available. If we cd back into ~/projects/examples_mise , it becomes available again; unless you explicitly install tools globally, mise will only make the tools available which are mentioned in a mise.toml file on the path from your current directory to the root of your file system. That of course means that we could potentially meet multiple mise.toml files when going back up to the root of the file system. Mise handles this by concatting the configurations and overwriting conflicting configurations, letting the file furthest down the tree win. This is a clever design as it allows us to configure different versions of the same tool to be available in different directories. Let\u2019s have a look at what the mise.toml file looks like: [tools] jj = \"latest\"     If we want a specific version of jj to be installed in a specific directory, we just update the toml file to say e.g. jj = \"0.30.0 . Managing multiple versions of a tool Let\u2019s see what it looks like to use mise to manage Python versions for two projects with different requirements: (Terminal session recording)   $  tree . \u251c\u2500\u2500 project_new\n\u2502\t\u2514\u2500\u2500 mise.toml\n\u2514\u2500\u2500 project_old\n    \u2514\u2500\u2500 mise.toml $  cat  project_new/mise.toml [ tools]\npython = \"3.11\" $  cat  project_old/mise.toml [ tools]\npython = \"3.8\" $  cd  project_new $  python --version Python 3.11.13 $  cd ../project_old $  python --version Python 3.8.20     When we cd into one of the directories listed above, mise automatically makes the version of the tool configured in mise.toml available to us. If it isn\u2019t already installed, mise will install it for us. The implication of this is that you can commit a mise.toml to your repository, and anyone that has mise installed will automatically get and use the expected dev tools when they enter the project directory. And when it\u2019s time to upgrade a dev tool, you can just update the version number in mise.toml and everyone will start using the new version! Use in CI/CD pipelines The fact that mise makes tools available to you according to the mise.toml file in your current working directory has further implications: it\u2019s not just developer machines that can benefit from using mise; CI/CD pipelines can benefit greatly as well! When you use mise in your pipelines, you avoid the problem of having out of sync versions between developer and build machines. You get to have a single place where you can configure the version of your dev tools everywhere! As I mentioned in the beginning, besides managing dev tools, mise also allows you to (https://mise.jdx.dev/tasks/toml-tasks.html) declare and run so-called tasks . Think of a task as an advanced invocation of a bash script. Even if we use tasks as just plain bash scripts (they can do a lot more), it can be a major advantage to declare common operations such as building, testing, linting etc. as mise tasks, since all developers get access to them and will run their commands in exactly the same way every time. If you\u2019re diligent in your naming, you can even make the experience of building or testing across projects identical. The following are examples of some very simple Python-related tasks declared in mise.toml : [tasks.install-deps] run = [ \"uv pip install -r requirements.txt\" ] [tasks.test] run = [ \"pytest .\" ]     Adding this to mise.toml will make the commands mise install-deps and mise test available. Again, if you check this in to your repo, the commands will be available to all developers and pipelines. And reusing these names in your rust project means that you can use the same commands to tell cargo to install your crates or run your tests. Once you\u2019ve declared your tasks you should of course also use them in your CI/CD pipeline. Doing this makes you less dependent on the particular yaml syntax and arbitrary requirements of your provider, and makes it easier to move to another one if you need to. It also ensures that there\u2019s a standard way to build and test your code, helping to further reduce the amount of \u201cit works on my machine\u201d. There\u2019s a lot of depth to what you can use mise to help you automate. It\u2019s a lovely tool and I hope I\u2019ve spiked your interest enough to give it a try! Security concerns Although this is a very obvious problem, I want to make it explicit: a major concern of all software dependency management is control of your supply chain; how easy is it for somebody to insert malicious code into a binary you will run hugely impacts the integrity of your systems and data. Depending on your industry, it might not be feasible to use mise as it\u2019s pretty opaque where your dependencies will be downloaded from. I'm hoping to find the time to write a series of posts over the summer on tools that I love. Here's the first one which I fell in love with just 3 months ago: mise(https://blog.vbang.dk/2025/06/29/tools-i-love-mise/) https://blog.vbang.dk/2025/06/29/tools-i-love-mise/  \u2014 Michael Vinter Bang (@micvbang) (https://twitter.com/micvbang/status/1939384107823137162?ref_src=twsrc%5Etfw) December 26, 2024   (Twitter settings iframe)    "
                ],
                "output": "htmltotext.txt",
                "pwd": "/data/archive/1751233099.942034",
                "schema": "ArchiveResult",
                "start_ts": "2025-06-29T21:38:59.933114+00:00",
                "status": "succeeded"
            }
        ],
        "media": [
            {
                "cmd": [
                    "/usr/local/bin/yt-dlp",
                    "--restrict-filenames",
                    "--trim-filenames",
                    "128",
                    "--write-description",
                    "--write-info-json",
                    "--write-annotations",
                    "--write-thumbnail",
                    "--no-call-home",
                    "--write-sub",
                    "--write-auto-subs",
                    "--convert-subs=srt",
                    "--yes-playlist",
                    "--continue",
                    "--no-abort-on-error",
                    "--ignore-errors",
                    "--geo-bypass",
                    "--add-metadata",
                    "--format=(bv*+ba/b)[filesize<=750m][filesize_approx<=?750m]/(bv*+ba/b)",
                    "--skip-download",
                    "--cache-dir=/data/yt-dlp-cache/",
                    "--cookies=/data/yt-dlp-cache/cookies.txt",
                    "--proxy=socks5://tor-socks-proxy:9150",
                    "--no-playlist",
                    "https://blog.vbang.dk/2025/06/29/tools-i-love-mise/"
                ],
                "cmd_version": "2024.10.7",
                "end_ts": "2025-06-29T21:39:07.789199+00:00",
                "index_texts": [],
                "output": "media/",
                "pwd": "/data/archive/1751233099.942034",
                "schema": "ArchiveResult",
                "start_ts": "2025-06-29T21:39:02.872848+00:00",
                "status": "succeeded"
            }
        ],
        "mercury": [
            {
                "cmd": [
                    "/home/archivebox/.npm/bin/postlight-parser",
                    "https://blog.vbang.dk/2025/06/29/tools-i-love-mise/"
                ],
                "cmd_version": "2.2.3",
                "end_ts": "2025-06-29T21:38:59.894571+00:00",
                "index_texts": null,
                "output": "mercury/",
                "pwd": "/data/archive/1751233099.942034",
                "schema": "ArchiveResult",
                "start_ts": "2025-06-29T21:38:56.632794+00:00",
                "status": "succeeded"
            }
        ],
        "pdf": [],
        "readability": [
            {
                "cmd": [
                    "/home/archivebox/.npm/bin/readability-extractor",
                    "/tmp/tmppoduuhji",
                    "https://blog.vbang.dk/2025/06/29/tools-i-love-mise/"
                ],
                "cmd_version": "0.0.11",
                "end_ts": "2025-06-29T21:38:46.812523+00:00",
                "index_texts": [
                    "Once in a while you get introduced to a tool that instantly changes the way you work. For me, mise is one of those tools.\n\nmise is the logical conclusion to a lot of the meta-tooling that exists around language-specific version and package managers like asdf, nvm, uv, pyenv etc. It makes it exceptionally easy to install, use, and manage software. It also allows you to manage environment variables and declare tasks (run commands).\n\n\nThe first step in getting an intuitive understanding of what mise can help you with is to use it to install a tool. Pick your favorite and try it out; it supports a lot!\n\nI recently read about jj in Thorsten Ball\u2019s newsletter and decided to try it out (again). I crossed my fingers and hoped that jj was one of the tools supported by mise and, to my delight, it was! The process looked something like this:\n\n$ jj\ncommand_not_found_handler:5: command not found: jj\n\n$ mise use jj\nmise ~/projects/examples_mise/mise.toml tools: jj@0.30.0\n\n$ jj version\njj 0.30.0\n\n$ cd ..\n\n$ jj version\ncommand_not_found_handler:5: command not found: jj\n\n$ cd eaxmples_mise\n\n$ jj version\njj 0.30.0\n\n\nAs the above shows, with mise we\u2019re just one command away from installing and trying out a new tool, e.g. mise use jj.\n\nIn the above we that mise printed mise ~/projects/examples_mise/mise.toml tools: jj@0.30.0. This tells us that mise has created (or updated) the mise configuration on that path. \nWe also see that if we cd out of ~/projects, the jj command is no longer available. If we cd back into ~/projects/examples_mise, it becomes available again; unless you explicitly install tools globally, mise will only make the tools available which are mentioned in a mise.toml file on the path from your current directory to the root of your file system. That of course means that we could potentially meet multiple mise.toml files when going back up to the root of the file system. Mise handles this by concatting the configurations and overwriting conflicting configurations, letting the file furthest down the tree win.\n\nThis is a clever design as it allows us to configure different versions of the same tool to be available in different directories. Let\u2019s have a look at what the mise.toml file looks like:\n\n\n\nIf we want a specific version of jj to be installed in a specific directory, we just update the toml file to say e.g. jj = \"0.30.0.\n\n\n\nLet\u2019s see what it looks like to use mise to manage Python versions for two projects with different requirements:\n\n\n\n$ tree\n.\n\u251c\u2500\u2500 project_new\n\u2502\t\u2514\u2500\u2500 mise.toml\n\u2514\u2500\u2500 project_old\n    \u2514\u2500\u2500 mise.toml\n\n$ cat project_new/mise.toml\n[tools]\npython = \"3.11\"\n\n$ cat project_old/mise.toml\n[tools]\npython = \"3.8\"\n\n$ cd project_new\n$ python --version\nPython 3.11.13\n\n$ cd ../project_old\n$ python --version\nPython 3.8.20\n\n\nWhen we cd into one of the directories listed above, mise automatically makes the version of the tool configured in mise.toml available to us. If it isn\u2019t already installed, mise will install it for us. The implication of this is that you can commit a mise.toml to your repository, and anyone that has mise installed will automatically get and use the expected dev tools when they enter the project directory. And when it\u2019s time to upgrade a dev tool, you can just update the version number in mise.toml and everyone will start using the new version!\n\nUse in CI/CD pipelines\n\nThe fact that mise makes tools available to you according to the mise.toml file in your current working directory has further implications: it\u2019s not just developer machines that can benefit from using mise; CI/CD pipelines can benefit greatly as well! When you use mise in your pipelines, you avoid the problem of having out of sync versions between developer and build machines. You get to have a single place where you can configure the version of your dev tools everywhere!\n\nAs I mentioned in the beginning, besides managing dev tools, mise also allows you to declare and run so-called tasks. Think of a task as an advanced invocation of a bash script. Even if we use tasks as just plain bash scripts (they can do a lot more), it can be a major advantage to declare common operations such as building, testing, linting etc. as mise tasks, since all developers get access to them and will run their commands in exactly the same way every time. If you\u2019re diligent in your naming, you can even make the experience of building or testing across projects identical.\n\nThe following are examples of some very simple Python-related tasks declared in mise.toml:\n\n[tasks.install-deps]\nrun = [\"uv pip install -r requirements.txt\"]\n\n[tasks.test]\nrun = [\"pytest .\"]\n\n\nAdding this to mise.toml will make the commands mise install-deps and mise test available. Again, if you check this in to your repo, the commands will be available to all developers and pipelines. And reusing these names in your rust project means that you can use the same commands to tell cargo to install your crates or run your tests.\n\nOnce you\u2019ve declared your tasks you should of course also use them in your CI/CD pipeline. Doing this makes you less dependent on the particular yaml syntax and arbitrary requirements of your provider, and makes it easier to move to another one if you need to. It also ensures that there\u2019s a standard way to build and test your code, helping to further reduce the amount of \u201cit works on my machine\u201d.\n\nThere\u2019s a lot of depth to what you can use mise to help you automate. It\u2019s a lovely tool and I hope I\u2019ve spiked your interest enough to give it a try!\n\nSecurity concerns\n\nAlthough this is a very obvious problem, I want to make it explicit: a major concern of all software dependency management is control of your supply chain; how easy is it for somebody to insert malicious code into a binary you will run hugely impacts the integrity of your systems and data. Depending on your industry, it might not be feasible to use mise as it\u2019s pretty opaque where your dependencies will be downloaded from.\n\nI'm hoping to find the time to write a series of posts over the summer on tools that I love. Here's the first one which I fell in love with just 3 months ago: mise https://blog.vbang.dk/2025/06/29/tools-i-love-mise/\u2014 Michael Vinter Bang (@micvbang) December 26, 2024"
                ],
                "output": "readability/",
                "pwd": "/data/archive/1751233099.942034",
                "schema": "ArchiveResult",
                "start_ts": "2025-06-29T21:38:44.227890+00:00",
                "status": "succeeded"
            }
        ],
        "screenshot": [],
        "singlefile": [],
        "title": [
            {
                "cmd": [
                    "/usr/bin/curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--proxy",
                    "socks5://tor-socks-proxy:9150",
                    "--max-time",
                    "60",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 ArchiveBox/{VERSION} (+https://github.com/ArchiveBox/ArchiveBox/)",
                    "https://blog.vbang.dk/2025/06/29/tools-i-love-mise/"
                ],
                "cmd_version": "8.10.1",
                "end_ts": "2025-06-29T21:38:43.052651+00:00",
                "index_texts": null,
                "output": "Tools I love: mise(-en-place)",
                "pwd": "/data/archive/1751233099.942034",
                "schema": "ArchiveResult",
                "start_ts": "2025-06-29T21:38:42.935902+00:00",
                "status": "succeeded"
            }
        ],
        "wget": []
    },
    "icons": null,
    "is_archived": true,
    "is_static": false,
    "latest": {
        "archive_org": "ArchiveError: Failed to find \"content-location\" URL header in Archive.org response.",
        "dom": "output.html",
        "favicon": "favicon.ico",
        "git": null,
        "media": "media/",
        "pdf": null,
        "screenshot": null,
        "singlefile": null,
        "title": "Tools I love: mise(-en-place)",
        "warc": null,
        "wget": null
    },
    "link_dir": "/data/archive/1751233099.942034",
    "newest_archive_date": "2025-06-29T21:39:07.841964+00:00",
    "num_failures": 1,
    "num_outputs": 8,
    "oldest_archive_date": "2025-06-29T21:38:22.155660+00:00",
    "path": "/2025/06/29/tools-i-love-mise/",
    "schema": "Link",
    "scheme": "https",
    "snapshot_abid": "snp_01JYYT0Y6D7309238F01WZ9W7K",
    "snapshot_id": "8925034e-741f-494b-a2c4-dcb039f4f0f3",
    "sources": [
        "/data/sources/1751233099-import.txt"
    ],
    "tags": null,
    "tags_str": "",
    "timestamp": "1751233099.942034",
    "title": "Tools I love: mise(-en-place)",
    "url": "https://blog.vbang.dk/2025/06/29/tools-i-love-mise/"
}