Rails 7 introduced a new bin/dev wrapper to launch and manage your Rails server, CSS watcher, and JS bundler into a single process, managed by foreman.
This is quite handy for running everything with a single command.
But what if you’re deploying to Heroku and using the Heroku CLI’s heroku local to run things locally?
Or if you’re a fan of one of the other tools that manage processes based on your Procfile?
I’ve got you covered!
bin/dev for heroku local
The biggest, and most obvious change is swapping out the executable.
Mostly this is to do with heroku local using the :<subcommand> style CLI interface.
Let’s compare foreman, heroku local, and bin/dev doing similar things to see how their CLIs differ.
# start the web and css processes
$ foreman start web,css
$ heroku local:start web,css
$ bin/dev web,css
It turns out bin/dev explicitly calls the foreman start command.
So a quick heroku local version of the same would be:
#!/usr/bin/env sh
if ! command -v heroku &> /dev/null; then
printf "You must install the Heroku CLI on your system before setup can continue\n"
printf "☁️ https://devcenter.heroku.com/articles/heroku-cli\n"
exit 1
fi
exec heroku local:start "$@"
And this works… fine-ish.
I mean, it totally works.
But it’s only using a small part of the underlying heroku local CLI.
And the same goes for the foreman version.
If we want to leverage the run or version commands, we’re out of luck.
A more robust bin/dev
If we want to leverage the other CLI commands, we’re going to need to do some bash-ing to check and manipulate the passed arguments.
Let’s start with the CLI we want to have.
$ bin/dev web,css # (implicit) start the web and css processes
$ bin/dev start web,css # (explicit) start the web and css processes
$ bin/dev run bin/rails c # start a rails console session
$ bin/dev version # check the foreman version
For this we need to default to the start command, but allow overriding it.
And we’ll need to pass other arguments on to heroku local.
#!/usr/bin/env bash
if ! command -v heroku &> /dev/null; then
printf "You must install the Heroku CLI on your system before setup can continue\n"
printf "☁️ https://devcenter.heroku.com/articles/heroku-cli\n"
exit 1
fi
cmd='start'
heroku_cmds=('run' 'start' 'version')
# If we were given any positional args we might need to handle sub-commands
if [[ $# -gt 0 ]];then
first_arg=${1}
# Shift heroku local commands off the array so we can pass remaining arguments along
if [[ " ${heroku_cmds[*]} " == *" ${first_arg} "* ]]; then
cmd="${first_arg}"
shift
fi
fi
exec heroku "local:${cmd}" "$@"
🎉 And just like that, it works!
We’ve got a bin/dev that works with heroku local and supports its other commands.
You can even bin/dev --help to see heroku local’s CLI help text.
I’ll leave it as an exercise to the reader to adapt this for node-foreman or other tools.