Multi-Pane Dev Tasks With Mise and WezTerm

Posted on Nov 19, 2025

I’ve finally transitioned all of my projects to have their tasks wrapped with Mise. I love how this lets me pop into any directory and type mise run to see the list of tasks for that project. I think this will be especially helpful in projects I don’t touch very often.

For example, here are the tasks I have for this blog:

A screenshot of the mise tasks for this blog, including “build” (to build for production), “dev” (to start the development server), and “new” (to create a new post)

I typically have several tasks to run when I’m working on a project - running the build, tailing logs, etc. It’s nice to have all these grouped in one terminal tab, so I create as many panes as I have tasks in a new WezTerm window and then manually start each task. It’s a bit tedious to do when switching contexts.

Yesterday, I wondered if there was a way to automate creating the WezTerm layout and sending the appropriate task to the appropriate pane. It turns out there is, and it isn’t too difficult!

A quick Kagi search led me to this GitHub discussion, which got me 99% of the way there.

Here’s an example from a Laravel project that I’m working on:

mise.toml
    [tools]
bun = 'latest'

[tasks.build]
description = "Build the application for production"
run = "bun run build"

[tasks.build-dev]
description = "Run development build tasks"
run = "bun run dev"

[tasks.pail]
description = "Tail logs with pail"
run = "php artisan pail -vv --timeout=0"

[tasks.queue]
description = "Run the queue worker"
run = "php artisan queue:work --verbose"

[tasks.phpstan]
description = "Run PHPStan"
run = "./vendor/bin/phpstan"

[tasks.arch]
description = "Run architecture tests"
run = "php artisan test --testsuite=Architecture"

[tasks.check]
description = "Run all static analysis checks"
depends = ["phpstan", "arch"]

[tasks.dev]
description = "Run development tasks in WezTerm panes"
run = """
run_command() {
    local pane_id
    local command_to_run
    pane_id="$1"
    command_to_run="$2"

    echo "$command_to_run\n" | wezterm cli send-text --no-paste --pane-id "$pane_id"
}
new_pane=$(wezterm cli spawn --cwd "$MISE_PROJECT_ROOT")
run_command "$new_pane" "mise run build-dev"
second_pane=$(wezterm cli split-pane --right --pane-id "$new_pane")
third_pane=$(wezterm cli split-pane --bottom --pane-id "$second_pane")
run_command "$second_pane" "mise run pail"
run_command "$third_pane" "mise run queue"
"""
  

mise run dev starts up Vite, tails the logs, and runs the queue worker in separate panes.

I can kill all the tasks at once with Cmd+w.

If you’ve ever used Laravel Solo, you might consider this a framework-agnostic alternative.

Hope someone else finds it helpful! 😄

PS - I realize that tmux sessions are much more powerful solution for this kind of thing, but I prefer using WezTerm’s native multiplexer.