Skip to content

Creating Pipelines

This guide walks you through creating pipelines to automate tasks with your voice.


  1. Open Freeway Preferences
  2. Go to the Pipelines tab
  3. Click Add First Pipeline (or Add Pipeline if you have existing ones)

Fill in the required fields:

  • Name: A descriptive name (e.g., “Uppercase Converter”)
  • Trigger Pattern: The text pattern to match (e.g., “make uppercase”)
  • Match Type: How to match the pattern (e.g., “Starts with”)
  • Shell Command: The command to run

Click the Try it button to test your pipeline:

  1. Enter sample input text
  2. Click Run
  3. View the output (or error)

Click Save to activate your pipeline.


A descriptive name for your pipeline. This appears in the pipeline list and in status messages.

The text pattern that activates this pipeline. Combined with the match type, this determines when your pipeline runs.

Tips:

  • Keep patterns short and distinct
  • Avoid patterns that overlap with normal speech
  • Test patterns to ensure they don’t trigger accidentally

Choose how the pattern is matched:

Match TypeBest For
Starts withCommands like “open…”, “search for…”
Ends withSuffixes like “…please”, “…now”
Exact matchSpecific phrases like “toggle dark mode”
ContainsKeywords that can appear anywhere
RegexComplex patterns with captures

The shell command to execute. This can be:

  • A simple command: date
  • A pipeline: tr '[:lower:]' '[:upper:]'
  • A script: python3 /path/to/script.py
  • Multiple commands: echo "hello" && say "hello"

Your command receives the transcribed text via:

Terminal window
# stdin - pipe-friendly
cat | your-command
# Environment variable - use in scripts
echo "$FREEWAY_TEXT"
OutputResult
Non-empty stdoutReplaces the transcribed text (pasted)
Empty stdoutSkip paste (nothing is pasted)
stderrShown as error message
Non-zero exit codeTreated as error

Transform text (output replaces input):

Terminal window
# Uppercase
tr '[:lower:]' '[:upper:]'
# Lowercase
tr '[:upper:]' '[:lower:]'
# Reverse lines
tac
# Sort lines
sort

Action only (empty output skips paste):

Terminal window
# Copy to clipboard
pbcopy
# Open URL
open "https://google.com"
# Play sound
afplay /System/Library/Sounds/Glass.aiff
# Show notification
osascript -e 'display notification "Done!" with title "Freeway"'

Both action and output:

Terminal window
# Copy to clipboard AND paste
tee >(pbcopy)
# Log AND output
tee -a /tmp/freeway.log

Matches if the transcribed text begins with the pattern.

Pattern: open Matches: “open terminal”, “open finder”, “open the door” Doesn’t match: “please open”, “reopen”

Terminal window
# Extract what to open
open_what=$(echo "$FREEWAY_TEXT" | sed 's/^open //')
open "$open_what"

Matches if the transcribed text ends with the pattern.

Pattern: please Matches: “help me please”, “do it please” Doesn’t match: “please help me”

Matches if the transcribed text exactly equals the pattern (case-insensitive).

Pattern: toggle dark mode Matches: “toggle dark mode”, “Toggle Dark Mode” Doesn’t match: “toggle the dark mode”, “dark mode toggle”

Matches if the pattern appears anywhere in the text.

Pattern: weather Matches: “what’s the weather”, “weather forecast”, “check weather please”

Matches using a regular expression (ICU syntax). Matching is case-insensitive. Text is normalized before matching: punctuation removed, whitespace trimmed.

Common patterns:

PatternMatches
^hey freewayText starting with “hey freeway”
please$Text ending with “please”
^(open|start) chat”open chat” or “start chat” at the beginning
^(open|launch|start)Text starting with “open”, “launch”, or “start”
send (email|message) to”send email to…” or “send message to…”
remind me in \d+ minutes”remind me in 5 minutes”, “remind me in 30 minutes”
^translate .+ to (spanish|french|german)$”translate hello to spanish”
^(what|who|where|when|why|how)\bQuestions starting with interrogative words
^search (for|on )?”search cats”, “search for cats”, “search on google”

Example — search command:

Pattern: ^search for (.+)$ Matches: “search for cats” → captures “cats”

Terminal window
# Using regex in shell
if [[ "$FREEWAY_TEXT" =~ ^search\ for\ (.+)$ ]]; then
query="${BASH_REMATCH[1]}"
open "https://google.com/search?q=$(echo "$query" | sed 's/ /+/g')"
fi

Example — multi-word trigger:

Pattern: ^(hey|ok|hi) freeway Matches: “hey freeway do something”, “ok freeway search”

Terminal window
# Strip trigger phrase and process the rest
command=$(echo "$FREEWAY_TEXT" | sed -E 's/^(hey|ok|hi) freeway[,]? *//')
echo "Command: $command"

Example — optional words:

Pattern: ^open (the )? Matches: “open terminal”, “open the finder”

Terminal window
# Extract app name, handling optional "the"
app=$(echo "$FREEWAY_TEXT" | sed -E 's/^open (the )?//')
open -a "$app"

For complex logic, call external scripts:

Terminal window
python3 /path/to/script.py
#!/usr/bin/env python3
import sys
text = sys.stdin.read()
# Process text...
print(text.upper())
Terminal window
/path/to/script.sh
#!/bin/bash
read text
# Process text...
echo "${text^^}" # Uppercase in bash 4+
Terminal window
osascript /path/to/script.scpt

Or inline:

Terminal window
osascript -e 'tell application "Finder" to make new folder'

Pipelines have a 30 second timeout. If your command takes longer, it will be terminated.

For long-running tasks:

  • Run them in the background: your-command &
  • Use disown or nohup
  • Start a detached process
Terminal window
# Run in background, no output (skip paste)
nohup long-running-task &>/dev/null &

Add logging to your shell command:

Terminal window
echo "Input: $FREEWAY_TEXT" >> /tmp/pipeline-debug.log
your-command | tee -a /tmp/pipeline-debug.log

Test commands in Terminal first:

Terminal window
echo "test input" | your-command
echo $? # Should be 0 for success

Errors appear in:

  • Status message in Freeway visualizer
  • Freeway debug console (menu bar → Debug)

  1. Test thoroughly — Use “Try it” before relying on a pipeline
  2. Keep patterns distinct — Avoid overlapping triggers
  3. Handle errors — Check for empty input, missing dependencies
  4. Use absolute paths — Don’t rely on PATH for scripts
  5. Avoid slow commands — Keep execution under a few seconds
  6. Order matters — Put specific patterns before general ones