Executables are the building blocks of flow automation. They can be simple commands, complex multi-step workflows, HTTP requests, or even GUI applications. This guide covers all executable types and configuration options.
Use the flow browse command to discover executables across your workspaces:
flow browse # Interactive multi-pane browser
flow browse --list # Simple list view
flow browse VERB ID # View specific executable detailsFilter executables by workspace, namespace, verb, or tag:
flow browse --workspace api --namespace v1 --verb deploy --tag production
flow browse --all --filter "database" # Search names and descriptionsEvery executable needs a verb and optionally a name:
executables:
- verb: run
name: my-task
description: "Does something useful"
tags: [development, automation]
aliases: [task, job]
timeout: 5m
visibility: public
exec:
cmd: echo "Hello, world!"- verb: Action type (run, build, test, deploy, etc.)
- name: Unique identifier within the namespace
- description: Markdown documentation for the executable
- tags: Labels for categorization and filtering
- aliases: Alternative names for the executable
- timeout: Maximum execution time (e.g., 30s, 5m, 1h)
- visibility: Access control (public, private, internal, hidden)
- public: Available from any workspace
- private: Only available within the same workspace but shown in browse lists (default)
- internal: Available within workspace but hidden from browse lists
- hidden: Cannot be run or listed
Customize executable behavior with environment variables using params or args.
Set environment variables from various sources:
executables:
- verb: deploy
name: app
exec:
file: deploy.sh
params:
# From secrets
- secretRef: api-token
envKey: API_TOKEN
- secretRef: production/database-url
envKey: DATABASE_URL
# Interactive prompts
- prompt: "Which environment?"
envKey: ENVIRONMENT
# Static values
- text: "production"
envKey: DEPLOY_ENVParameter types:
secretRef: Reference to vault secretprompt: Interactive user inputtext: Static value
Handle command-line arguments:
executables:
- verb: build
name: container
exec:
file: build.sh
args:
# Positional argument
- pos: 1
envKey: IMAGE_TAG
required: true
# Flag arguments
- flag: publish
envKey: PUBLISH
type: bool
default: false
- flag: registry
envKey: REGISTRY
default: "docker.io"Run with arguments:
flow build container v1.2.3 publish=true registry=my-registry.comArgument types:
pos: Positional argument (by position number, starting from 1)flag: Named flag argumenttype: Validation type (string, int, float, bool)
Override any environment variable with --param:
flow deploy app --param API_TOKEN=override --param ENVIRONMENT=stagingControl where executables run with the dir field:
executables:
- verb: build
name: frontend
exec:
cmd: npm run build
dir: "./frontend" # Relative to flowfile
- verb: clean
name: downloads
exec:
cmd: rm -rf downloads/*
dir: "~/Downloads" # User home directory
- verb: deploy
name: from-root
exec:
cmd: kubectl apply -f k8s/
dir: "//" # Workspace root
- verb: test
name: isolated
exec:
cmd: |
echo "Running in temporary directory"
ls -la
dir: "f:tmp" # Temporary directory (auto-cleaned)Directory prefixes:
//: Workspace root directory~/: User home directory./: Current working directoryf:tmp: Temporary directory (auto-cleaned)$VAR: Environment variable expansion
Run commands or scripts directly:
executables:
- verb: build
name: app
exec:
cmd: npm run build && npm test
- verb: deploy
name: app
exec:
file: deploy.sh
logMode: json # text, logfmt, json, or hiddenOptions:
cmd: Inline command to runfile: Script file to executelogMode: How to format command output
Run multiple steps in order:
executables:
- verb: deploy
name: full-stack
serial:
failFast: true # Stop on first failure
execs:
- cmd: docker build -t api .
- cmd: docker build -t web ./frontend
- ref: test api
- cmd: kubectl apply -f k8s/
retries: 3
- cmd: kubectl rollout status deployment/api
reviewRequired: true # Pause for user confirmationThe executable environment variables and executable directory of the parent executable are inherited by the child executables.
Options:
failFast: Stop execution on first failure (default: true)retries: Number of times to retry failed stepsreviewRequired: Pause for user confirmation
Run multiple steps simultaneously:
executables:
- verb: test
name: all-suites
parallel:
maxThreads: 4 # Limit concurrent operations
failFast: false # Run all tests even if some fail
execs:
- cmd: npm run test:unit
- cmd: npm run test:integration
- cmd: npm run test:e2e
- ref: lint code
retries: 1The executable environment variables and executable directory of the parent executable are inherited by the child executables.
Options:
maxThreads: Maximum concurrent operations (default: 5)failFast: Stop all operations on first failure (default: true)retries: Number of times to retry failed operations
Open files, URLs, or applications:
executables:
- verb: open
name: workspace
launch:
uri: "$FLOW_WORKSPACE_PATH"
app: "Visual Studio Code"
- verb: open
name: docs
launch:
uri: "https://flowexec.io"
- verb: open
name: note
launch:
uri: "./note.md"
app: "Obsidian"Options:
uri: File path or URL to open (required)app: Specific application to use
Make HTTP requests to APIs:
executables:
- verb: deploy
name: webhook
request:
method: POST
url: "https://api.example.com/deploy"
headers:
Authorization: "Bearer $API_TOKEN"
Content-Type: "application/json"
body: |
{
"environment": "$ENVIRONMENT",
"version": "$VERSION"
}
timeout: 30s
validStatusCodes: [200, 201]
logResponse: true
transformResponse: |
"Deployment " + fromJSON(data)["status"]
responseFile:
filename: "deploy-response.json"Options:
method: HTTP method (GET, POST, PUT, PATCH, DELETE)url: Request URL (required)headers: Custom headersbody: Request bodytimeout: Request timeoutvalidStatusCodes: Acceptable status codeslogResponse: Log response bodytransformResponse: Transform response with ExprresponseFile: Save response to file
Generate and display markdown with templates:
executables:
- verb: show
name: status
render:
templateFile: "status-template.md"
templateDataFile: "status-data.json"Template file example:
# System Status
Current time: {{ .timestamp }}
## Services
{{- range .services }}
- **{{ .name }}**: {{ .status }}
{{- end }}
## Metrics
- CPU: {{ .cpu }}%
- Memory: {{ .memory }}%Options:
templateFile: Markdown template file (required)templateDataFile: JSON/YAML data file
Generate executables from shell scripts, Makefiles, package.json scripts, or docker-compose services:
# In flowfile
imports:
- "scripts/deploy.sh"
- "scripts/backup.sh"
- "Makefile"
- "frontend/package.json"
- "docker-compose.yaml"All imported executables are automatically tagged with generated and their file type (e.g., docker-compose, makefile, package.json).
Shell scripts are imported as single executables with the script's filename as the name and exec as the default verb.
You can use special comments to override executable metadata:
#!/bin/bash
# scripts/deploy.sh
# f:name=production f:verb=deploy
# f:description="Deploy to production environment"
# f:tags=production,critical
# f:aliases=prod-deploy
# f:visibility=internal
# f:timeout=10m
echo "Deploying to production..."
kubectl apply -f k8s/Supported comment keys:
name,verb,description,tags,aliases,visibility,timeout
Multi-line descriptions:
# f:name=backup f:verb=run
# <f|description>
# Creates a backup of the database
# and uploads it to S3 storage
# <f|description>Makefile targets are imported as executables with a verb and name that best represents the target.
# Makefile
# f:name=app f:verb=build f:description="Build the application"
build:
go build -o bin/app ./cmd/app
# Run all tests
test:
go test ./...
# f:visibility=internal
clean:
rm -rf bin/The same comment parsing syntax works in Makefiles - use # f:key=value to override executable configuration.
NPM scripts from package.json are imported as executables with a verb and name that best represents the script name.
{
"scripts": {
"build": "webpack --mode production",
"test": "jest",
"dev": "webpack-dev-server --mode development",
"lint": "eslint src/"
}
}This creates executables like:
build- Runs the build scripttest- Runs the test scriptstart dev- Runs the development serverlint- Runs the linter
Docker Compose files are imported to create executables for managing services:
# docker-compose.yml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
db:
image: postgres:13
environment:
POSTGRES_DB: myapp
redis:
image: redis:6This creates executables like:
start app- Start the app servicestart db- Start the database servicestart redis- Start the Redis servicestart(alias: all, services) - Start all servicesstop(alias: all, services) - Stop all servicesbuild app- Build the app service (if build config exists)
Reference other executables to build modular workflows:
executables:
# Reusable components
- verb: build
name: api
exec:
cmd: docker build -t api .
- verb: test
name: api
exec:
cmd: npm test
# Composite workflows
- verb: deploy
name: full
serial:
execs:
- ref: build api
- ref: test api
- cmd: kubectl apply -f api.yaml
# Cross-workspace references (requires public visibility)
- verb: deploy
name: with-monitoring
serial:
execs:
- ref: deploy full
- ref: trigger monitoring/slack:deployment-completeReference formats:
ref: build api- Current workspace/namespaceref: build workspace/namespace:api- Full referenceref: build workspace/api- Specific workspaceref: build namespace:api- Specific namespace
Cross-workspace requirements:
- Referenced executables must have
visibility: public - Private, internal, and hidden executables cannot be cross-referenced
Now that you understand all executable types and options:
- Build complex workflows → Advanced workflows
- Secure your automation → Working with secrets
- Generate project templates → Templates & code generation