Terminal Shortcut for macOS iTerm: Launch Your Dev Environment with One Command

Spinning up a full stack project usually means opening terminals, cd-ing into folders, killing ports, running servers, maybe opening VS Code… every. single. time.
This shortcut wraps all of that into one command: it opens iTerm, creates labeled tabs for each service (backend, frontend, ngrok, etc.), kills any lingering processes on the right ports, starts everything, and (optionally) opens the folder in VS Code.
What you’ll build
dev-insyte
# or, to auto-open VS Code on each tab's directory:
dev-insyte --open-vs-code
The script
✅ Copy this into ~/.scripts/dev-insyte
🔒 Replace any secret values with your own secure env handling (see notes below)
#!/bin/bash
OPEN_VSCODE=false
# Parse flags
for arg in "$@"; do
if [ "$arg" = "--open-vs-code" ]; then
OPEN_VSCODE=true
fi
done
# Define function to append "code ." if flag is present
append_code_command() {
local dir="$1"
if $OPEN_VSCODE; then
echo "cd $dir && code ."
else
echo "cd $dir"
fi
}
osascript <<'EOF'
tell application "iTerm"
activate
set newWindow to (create window with default profile)
-- Tab 1: Flowise (example service)
tell current session of newWindow
set name to "Flowise"
write text "echo -ne '\\033]0;Flowise\\007';"
write text "lsof -ti:3001 | xargs kill -9;"
write text "STORAGE_TYPE=s3 S3_STORAGE_BUCKET_NAME=<YOUR_BUCKET> S3_STORAGE_ACCESS_KEY_ID=<YOUR_KEY_ID> S3_STORAGE_SECRET_ACCESS_KEY=<YOUR_SECRET> S3_STORAGE_REGION=ap-southeast-1 PORT=3001 flowise start;"
end tell
-- Tab 2: Backend
tell newWindow
set backendTab to (create tab with default profile)
tell current session of backendTab
set name to "Backend"
write text "echo -ne '\\033]0;Backend\\007';"
write text "$(append_code_command "/Users/dia/dev/projects/insyte/insyte-be")"
write text "lsof -ti:3000 | xargs kill -9; cd /Users/dia/dev/projects/insyte/insyte-be && npm run start:dev"
end tell
end tell
-- Tab 3: Frontend
tell newWindow
set frontendTab to (create tab with default profile)
tell current session of frontendTab
set name to "Frontend"
write text "echo -ne '\\033]0;Frontend\\007';"
write text "$(append_code_command "/Users/dia/dev/projects/insyte/insyte-fe")"
write text "lsof -ti:5173 | xargs kill -9; cd /Users/dia/dev/projects/insyte/insyte-fe && npm run dev"
end tell
end tell
-- Tab 4: ngrok
tell newWindow
set webhookTab to (create tab with default profile)
tell current session of webhookTab
set name to "ngrok"
write text "echo -ne '\\033]0;ngrok\\007';"
write text "ngrok http 3000 --domain=devacademe.ngrok.dev"
end tell
end tell
end tell
EOF
Make it executable and add a shortcut
chmod +x ~/.scripts/dev-insyte
In your shell config (~/.zshrc or ~/.bashrc):
alias dev-insyte=~/.scripts/dev-insyte
Reload your shell:
source ~/.zshrc # or ~/.bashrc
How it works (line-by-line tour)
1) Flag parsing: --open-vs-code
OPEN_VSCODE=false
for arg in "$@"; do
if [ "$arg" = "--open-vs-code" ]; then
OPEN_VSCODE=true
fi
done
Looks for --open-vs-code in the command you run.
If present, the script will open VS Code in the relevant tab’s directory.
2) Smart “cd” helper
append_code_command() {
local dir="$1"
if $OPEN_VSCODE; then
echo "cd $dir && code ."
else
echo "cd $dir"
fi
}
Returns a string you can inject into iTerm that either:
just cds into the folder, or
cds and launches VS Code (code .) if the flag is set.
3) Talking to iTerm via AppleScript
osascript <<'EOF'
# ... AppleScript ...
EOF
osascript executes AppleScript.
The here-doc (<<'EOF') keeps the script contents intact and avoids Bash expanding special characters inside.
4) Create a new iTerm window
tell application "iTerm"
activate
set newWindow to (create window with default profile)
- Brings iTerm to front and opens a window using your default profile.
5) Each tab = one service
Inside each tab you see:
Set the tab title in the iTerm UI
echo -ne '\033]0;Flowise\007'
- That escape sequence updates the terminal title to “Flowise” (or “Backend”, “Frontend”, etc.).
Kill whatever already uses the port (optional but useful)
lsof -ti:3001 | xargs kill -9
lsof -ti:PORT finds PIDs bound to the port.
xargs kill -9 force-kills them so your server can bind.
⚠️ Be careful: this kills any process on that port.
Export env + start the process
STORAGE_TYPE=s3 S3_STORAGE_BUCKET_NAME=... PORT=3001 flowise start
Sets environment variables for this command only.
Starts the service (flowise start in this example).
Navigate + run your script
$(append_code_command "/path/to/project")
lsof -ti:3000 | xargs kill -9; cd /path/to/project && npm run start:dev
Jumps to the project folder (and opens VS Code if --open-vs-code was used).
Kills the port, then starts your dev server.
Open tunnels
ngrok http 3000 --domain=devacademe.ngrok.dev
- Exposes your local backend to the internet for webhooks or teammates.
6) Tab overview in this setup
Tab 1: Flowise — starts Flowise on port 3001 with S3-style env.
Tab 2: Backend — npm run start:dev on 3000.
Tab 3: Frontend — Vite dev server on 5173.
Tab 4: ngrok — tunnels 3000 to a custom domain.
Using it
Basic:
dev-insyte
Open VS Code in backend/frontend tabs automatically:
dev-insyte --open-vs-code
Customize it for your project
Change paths:
- Replace /Users/dia/dev/projects/insyte/insyte-be and insyte-fe with your folders.
Change ports:
- Update 3000, 3001, 5173 to match your services.
Change commands:
- Swap npm run start:dev with pnpm dev, bun dev, docker compose up, etc.
Add/Remove tabs:
- Duplicate a tab block to add Redis, database UI, worker queues, etc.
Summary
You now have a one-liner that:
Opens iTerm with labeled tabs,
Jumps into the right folders (and optionally opens VS Code),
Frees busy ports,
Boots all your dev services and a public tunnel.
It’s a tiny quality-of-life improvement that adds up every single day. Happy shipping! 🚀
Subscribe to my newsletter
Read articles from Bret Axl Sebastian Pura directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
