The routines command drives the Routines Mac app from your
terminal: routines and their outputs, flows, snippets, shared memory, meetings,
to-dos, and the app's Gmail, Google Calendar, and Slack connectors. It is also
the bridge that lets AI agents use Routines as a tool.
Install
There is nothing to install. The CLI ships inside the app bundle at
Routines.app/Contents/MacOS/routines-cli, and the app links it onto your
PATH as routines, trying /usr/local/bin first, then /opt/homebrew/bin,
then ~/.local/bin. It updates with the app, and routines --version tells
you which version you have.
The CLI is a thin client. It reads the local Routines SQLite database and, for actions, talks over a local socket to the running app. It ships no network stack or credentials of its own, so run it directly on your Mac, not inside a sandbox, container, or CI runner that is isolated from your desktop session.
When the app has to be running
Commands come in two kinds, and every command below carries a label:
- Works with the app closed. Reads such as
list,show,outputs,memory search,meetings list,library search,todos,connectors, andclaude sessionsanswer straight from the local database or the process table. - Requires the Routines app running. Everything that changes data or
reaches a connected service goes through the app. If it is not running, the
command says so; open the app with
open -a Routinesand run it again.
Two conventions run through the reference: most read commands accept --json
for machine-readable output (each command's table says so), and every command
accepts -h/--help and -V/--version.
Commands
Routines: list · show · outputs · create · edit · delete · enable · disable · run
Flows: flows list · flows show · flows create · flows delete · flows rename · flows add-step · flows remove-step · flows connect · flows disconnect · flows set-input · flows run · flows trace
Snippets: snippets list · snippets show · snippets add · snippets edit · snippets delete · snippets enable · snippets disable · snippets on · snippets off · snippets status
Knowledge and memory: memory search · meetings list · meetings show · library list · library show · library search · workspace · workspace path · connectors
To-dos: todos · todos list · todos today · todos overdue · todos show · todos add · todos done · todos reopen · todos edit · todos prompt · todos run · todos delete
Email, calendar, Slack, and tools: email search · email send · email attachment · calendar today · calendar week · slack read · tools list · tools call
Claude Code sessions: claude terminal · claude browser · claude sessions · goal
Agent integration: agent-docs · mcp · skill
Routines
Create, inspect, and run the scheduled AI routines the app manages. Reading works with the app closed; creating, editing, and running go through the app.
list
Works with the app closed
List all routines
routines list [OPTIONS]
| Option | Description |
|---|---|
--json |
Output as JSON |
routines list
routines list --json
show
Works with the app closed
Show a routine by name or id
routines show [OPTIONS] <ROUTINE>
| Argument | Description |
|---|---|
<ROUTINE> |
Routine name or id |
| Option | Description |
|---|---|
--json |
Output as JSON |
routines show "Morning briefing"
outputs
Works with the app closed
Show recent outputs of a routine
routines outputs [OPTIONS] <ROUTINE>
| Argument | Description |
|---|---|
<ROUTINE> |
Routine name or id |
| Option | Description |
|---|---|
--last |
Only the most recent output, printed in full |
--limit <LIMIT> |
Maximum number of outputs to show [default: 5] |
--full |
Print full content without truncation |
--html |
Print only the trailing ```html visual report of the most recent output to stdout (e.g. --html > report.html). Fails if the run has no visual output |
--json |
Output as JSON |
routines outputs "Morning briefing" --last
routines outputs "Morning briefing" --limit 10
routines outputs "Morning briefing" --html > report.html
--html extracts the visual report of the most recent run, ready to open in a browser.
create
Requires the Routines app running
Create a new routine (requires the Routines app to be running)
routines create [OPTIONS] --name <NAME> --prompt <PROMPT>
| Option | Description |
|---|---|
--name <NAME> |
Routine name |
--prompt <PROMPT> |
What the routine should do (its prompt) |
--description <DESCRIPTION> |
Optional description |
--schedule <SCHEDULE> |
Natural-language schedule, e.g. "every weekday at 9am" |
--cron <CRON> |
Exact cron expression, e.g. "0 9 * * 1-5" |
--timezone <TIMEZONE> |
IANA timezone, e.g. "Europe/Bucharest" (defaults to the system timezone) |
--intelligence <INTELLIGENCE> |
Intelligence level [default: fast] [possible values: fast, smart] |
--engine <ENGINE> |
Execution engine: claude (Claude Code subscription) or api (app API key) Possible values: claude (Run through your local Claude Code (your Claude subscription)); api (Run through the API key configured in the app) |
--max-iterations <MAX_ITERATIONS> |
Retry cap for goal routines: how many times it retries until its success criteria are met (scheduled routines ignore this) [default: 5] |
--json |
Output as JSON |
routines create \
--name "Morning briefing" \
--prompt "Summarize my unread email and today's calendar" \
--schedule "every weekday at 9am"
edit
Requires the Routines app running
Edit an existing routine (requires the Routines app to be running)
routines edit [OPTIONS] <ROUTINE>
| Argument | Description |
|---|---|
<ROUTINE> |
Routine name or id |
| Option | Description |
|---|---|
--name <NAME> |
New routine name |
--prompt <PROMPT> |
New prompt |
--description <DESCRIPTION> |
New description |
--schedule <SCHEDULE> |
New natural-language schedule |
--cron <CRON> |
New cron expression |
--timezone <TIMEZONE> |
New IANA timezone |
--intelligence <INTELLIGENCE> |
New intelligence level [possible values: fast, smart] |
--engine <ENGINE> |
Execution engine: claude (Claude Code subscription) or api (app API key) Possible values: claude (Run through your local Claude Code (your Claude subscription)); api (Run through the API key configured in the app) |
--max-iterations <MAX_ITERATIONS> |
Retry cap for goal routines: how many times it retries until its success criteria are met (scheduled routines ignore this) |
--json |
Output as JSON |
routines edit "Morning briefing" --prompt "Also include unread Slack messages"
delete
Requires the Routines app running
Delete a routine (requires the Routines app to be running)
routines delete [OPTIONS] <ROUTINE>
| Argument | Description |
|---|---|
<ROUTINE> |
Routine name or id |
| Option | Description |
|---|---|
--force |
Skip the confirmation prompt |
routines delete "Morning briefing" --force
enable
Requires the Routines app running
Enable a routine (requires the Routines app to be running)
routines enable <ROUTINE>
| Argument | Description |
|---|---|
<ROUTINE> |
Routine name or id |
routines enable "Morning briefing"
disable
Requires the Routines app running
Disable a routine (requires the Routines app to be running)
routines disable <ROUTINE>
| Argument | Description |
|---|---|
<ROUTINE> |
Routine name or id |
routines disable "Morning briefing"
run
Requires the Routines app running
Run a routine immediately (requires the Routines app to be running)
routines run [OPTIONS] <ROUTINE>
| Argument | Description |
|---|---|
<ROUTINE> |
Routine name or id |
| Option | Description |
|---|---|
--engine <ENGINE> |
Engine override for this run only Possible values: claude (Run through your local Claude Code (your Claude subscription)); api (Run through the API key configured in the app) |
--json |
Output as JSON |
routines run "Morning briefing"
routines run "Morning briefing" --engine claude
A run can take a while. Read its result afterwards with routines outputs "<name>" --last.
Flows
A flow chains routines into one graph with optional plain-language checks between steps. Every flows command talks to the running app.
flows list
Requires the Routines app running
List every flow
routines flows list [OPTIONS]
| Option | Description |
|---|---|
--json |
Output as JSON |
routines flows list
flows show
Requires the Routines app running
Show a flow: its steps, connections, input question and last run
routines flows show [OPTIONS] <FLOW>
| Argument | Description |
|---|---|
<FLOW> |
Flow name or id |
| Option | Description |
|---|---|
--json |
Output as JSON |
routines flows show "Content pipeline"
flows create
Requires the Routines app running
Create a flow (requires the Routines app to be running)
routines flows create [OPTIONS] --name <NAME>
| Option | Description |
|---|---|
--name <NAME> |
Name for the new flow |
--schedule <SCHEDULE> |
When it runs, in plain words ("every weekday at 8am") or as cron ("0 8 * * 1-5"). Without one the flow only runs when you run it |
--timezone <TIMEZONE> |
IANA timezone for the schedule (defaults to this Mac's) |
--json |
Output as JSON |
routines flows create --name "Content pipeline" --schedule "every weekday at 8am"
flows delete
Requires the Routines app running
Delete a flow (the routines it runs are left alone)
routines flows delete [OPTIONS] <FLOW>
| Argument | Description |
|---|---|
<FLOW> |
Flow name or id |
| Option | Description |
|---|---|
--force |
Skip the confirmation prompt |
--json |
Output as JSON |
routines flows delete "Content pipeline" --force
flows rename
Requires the Routines app running
Rename a flow
routines flows rename [OPTIONS] <FLOW> <NAME>
| Argument | Description |
|---|---|
<FLOW> |
Flow name or id |
<NAME> |
The new name |
| Option | Description |
|---|---|
--json |
Output as JSON |
routines flows rename "Content pipeline" "Publishing pipeline"
flows add-step
Requires the Routines app running
Add a routine to a flow as a step
routines flows add-step [OPTIONS] <FLOW> <ROUTINE>
| Argument | Description |
|---|---|
<FLOW> |
Flow name or id |
<ROUTINE> |
Routine name or id |
| Option | Description |
|---|---|
--json |
Output as JSON |
routines flows add-step "Content pipeline" "Draft the post"
flows remove-step
Requires the Routines app running
Remove a step from a flow
routines flows remove-step [OPTIONS] <FLOW> <STEP>
| Argument | Description |
|---|---|
<FLOW> |
Flow name or id |
<STEP> |
Step name (the routine it runs) or step id |
| Option | Description |
|---|---|
--json |
Output as JSON |
routines flows remove-step "Content pipeline" "Draft the post"
flows connect
Requires the Routines app running
Connect one step to another
routines flows connect [OPTIONS] <FLOW> <FROM> <TO>
| Argument | Description |
|---|---|
<FLOW> |
Flow name or id |
<FROM> |
Step the connection leads from |
<TO> |
Step the connection leads to |
| Option | Description |
|---|---|
--check <CHECK> |
Plain-language condition the connection is gated on |
--on-fail <ON_FAIL> |
What happens when the check says no (needs --check) Possible values: halt (Stop this branch of the flow); retry (Send the earlier step back for another attempt, with the critique) |
--max-loops <MAX_LOOPS> |
How many times a retry may send the earlier step back (needs --on-fail retry) |
--json |
Output as JSON |
routines flows connect "Content pipeline" "Draft the post" "Publish it" \
--check "the draft has a headline and is longer than 200 words" \
--on-fail retry --max-loops 3
flows disconnect
Requires the Routines app running
Remove the connection between two steps
routines flows disconnect [OPTIONS] <FLOW> <FROM> <TO>
| Argument | Description |
|---|---|
<FLOW> |
Flow name or id |
<FROM> |
Step the connection leads from |
<TO> |
Step the connection leads to |
| Option | Description |
|---|---|
--json |
Output as JSON |
routines flows disconnect "Content pipeline" "Draft the post" "Publish it"
flows set-input
Requires the Routines app running
Ask (or stop asking) for a sentence before the flow runs
routines flows set-input [OPTIONS] --ask <ASK> <FLOW>
| Argument | Description |
|---|---|
<FLOW> |
Flow name or id |
| Option | Description |
|---|---|
--ask <ASK> |
Whether pressing Run asks for input first [possible values: on, off] |
--hint <HINT> |
The example shown in that box |
--json |
Output as JSON |
routines flows set-input "Content pipeline" --ask on --hint "What should I write about?"
flows run
Requires the Routines app running
Start a flow now
routines flows run [OPTIONS] <FLOW>
| Argument | Description |
|---|---|
<FLOW> |
Flow name or id |
| Option | Description |
|---|---|
--input <INPUT> |
What this run should work on |
--json |
Output as JSON |
routines flows run "Content pipeline" --input "our Q3 numbers"
Starts the flow and returns immediately with a run id; the flow keeps working in the app. Read the result with flows trace.
flows trace
Requires the Routines app running
Show what happened in a run, step by step
routines flows trace [OPTIONS] <FLOW>
| Argument | Description |
|---|---|
<FLOW> |
Flow name or id |
| Option | Description |
|---|---|
--run <RUN> |
Run id (defaults to the most recent run) |
--json |
Output as JSON |
routines flows trace "Content pipeline"
routines flows trace "Content pipeline" --run 3f2a1b0c
Snippets
A snippet is a keyword the app expands into stored text as you type, anywhere on the Mac. Every snippets command talks to the running app.
snippets list
Requires the Routines app running
List every snippet
routines snippets list [OPTIONS]
| Option | Description |
|---|---|
--json |
Output as JSON |
routines snippets list
snippets show
Requires the Routines app running
Show one snippet, including its full text
routines snippets show [OPTIONS] <SNIPPET>
| Argument | Description |
|---|---|
<SNIPPET> |
Snippet name, keyword or id |
| Option | Description |
|---|---|
--json |
Output as JSON |
routines snippets show "Signature"
snippets add
Requires the Routines app running
Add a snippet (requires the Routines app to be running)
routines snippets add --name <NAME> --keyword <KEYWORD> --content <CONTENT>
| Option | Description |
|---|---|
--name <NAME> |
What to call it |
--keyword <KEYWORD> |
The trigger you type, e.g. ";sig" |
--content <CONTENT> |
The text it expands to, or "-" to read it from stdin |
routines snippets add --name "Signature" --keyword ";sig" --content "Best, Eduard"
pbpaste | routines snippets add --name "Signature" --keyword ";sig" --content -
The app normalizes every keyword to a ; prefix, so --keyword sig is stored as ;sig. --content - reads stdin to EOF and stores it byte for byte.
snippets edit
Requires the Routines app running
Change a snippet's name, keyword or text
routines snippets edit [OPTIONS] <SNIPPET>
| Argument | Description |
|---|---|
<SNIPPET> |
Snippet name, keyword or id |
| Option | Description |
|---|---|
--name <NAME> |
New name |
--keyword <KEYWORD> |
New keyword |
--content <CONTENT> |
New text, or "-" to read it from stdin |
routines snippets edit "Signature" --keyword ";sign"
cat signature.txt | routines snippets edit "Signature" --content -
snippets delete
Requires the Routines app running
Delete a snippet
routines snippets delete [OPTIONS] <SNIPPET>
| Argument | Description |
|---|---|
<SNIPPET> |
Snippet name, keyword or id |
| Option | Description |
|---|---|
--force |
Skip the confirmation prompt |
routines snippets delete "Signature" --force
snippets enable
Requires the Routines app running
Turn one snippet back on
routines snippets enable <SNIPPET>
| Argument | Description |
|---|---|
<SNIPPET> |
Snippet name, keyword or id |
routines snippets enable "Signature"
snippets disable
Requires the Routines app running
Stop one snippet from expanding
routines snippets disable <SNIPPET>
| Argument | Description |
|---|---|
<SNIPPET> |
Snippet name, keyword or id |
routines snippets disable "Signature"
snippets on
Requires the Routines app running
Turn snippet expansion on everywhere
routines snippets on
routines snippets on
snippets off
Requires the Routines app running
Turn snippet expansion off everywhere
routines snippets off
routines snippets off
A master switch: nothing expands until snippets on, not even snippets that are individually enabled.
snippets status
Requires the Routines app running
Whether snippets expand, and how many you have
routines snippets status [OPTIONS]
| Option | Description |
|---|---|
--json |
Output as JSON |
routines snippets status --json
Knowledge and memory
Search shared memory, browse recorded meetings and the Library, and locate the markdown workspace. These read the local database and work with the app closed.
memory search
Works with the app closed
Search shared memory
routines memory search [OPTIONS] <QUERY>
| Argument | Description |
|---|---|
<QUERY> |
Search query |
| Option | Description |
|---|---|
--limit <LIMIT> |
Maximum number of results [default: 10] |
--json |
Output as JSON |
routines memory search "project deadline"
routines memory search "project deadline" --limit 20 --json
meetings list
Works with the app closed
List recorded meetings
routines meetings list [OPTIONS]
| Option | Description |
|---|---|
--limit <LIMIT> |
Maximum number of meetings to show [default: 20] |
--json |
Output as JSON |
routines meetings list --limit 50
meetings show
Works with the app closed
Show one meeting's transcript and notes
routines meetings show [OPTIONS] <ID>
| Argument | Description |
|---|---|
<ID> |
Meeting id |
| Option | Description |
|---|---|
--full |
Print the full transcript without truncation |
--json |
Output as JSON |
routines meetings show <id> --full
library list
Works with the app closed
List captured library items, newest first
routines library list [OPTIONS]
| Option | Description |
|---|---|
--limit <LIMIT> |
Maximum number of items to show [default: 20] |
--kind <KIND> |
Only items of this kind (e.g. "article") |
--json |
Output as JSON |
routines library list --kind article --limit 50
library show
Works with the app closed
Show one item by id prefix or title substring
routines library show [OPTIONS] <ITEM>
| Argument | Description |
|---|---|
<ITEM> |
Library item id (or a unique id prefix / title substring) |
| Option | Description |
|---|---|
--full |
Also print the full enriched note from the vault |
--json |
Output as JSON |
routines library show "self-writing vault" --full
library search
Works with the app closed
Full-text search the Library
routines library search [OPTIONS] <QUERY>
| Argument | Description |
|---|---|
<QUERY> |
Search query |
| Option | Description |
|---|---|
--limit <LIMIT> |
Maximum number of results [default: 10] |
--json |
Output as JSON |
routines library search "obsidian vault"
workspace
Works with the app closed
Show the knowledge base: workspace root and memory sections
routines workspace [OPTIONS] [COMMAND]
| Option | Description |
|---|---|
--json |
Output as JSON |
routines workspace
routines workspace --json
workspace path
Works with the app closed
Print only the resolved workspace root path
routines workspace path [OPTIONS]
| Option | Description |
|---|---|
--json |
Output as JSON |
routines workspace path
connectors
Works with the app closed
List connected services (Gmail, Calendar, Slack, MCP servers)
routines connectors [OPTIONS]
| Option | Description |
|---|---|
--json |
Output as JSON |
routines connectors
routines connectors --json
MCP server addresses are printed host-and-path only: a token riding in the query string is stripped, so nothing here is a usable credential.
To-dos
The user's real task list, the same one the app shows. Reads work with the app closed; every change goes through the running app.
todos
Works with the app closed
Work with the user's to-dos (no subcommand lists the open ones)
routines todos [OPTIONS] [COMMAND]
| Option | Description |
|---|---|
--json |
Output as JSON |
routines todos
todos list
Works with the app closed
List to-dos, open ones first
routines todos list [OPTIONS]
| Option | Description |
|---|---|
--all |
Include completed to-dos |
--limit <LIMIT> |
Maximum number of to-dos to show [default: 50] |
--json |
Output as JSON |
routines todos list --all --limit 100 --json
todos today
Works with the app closed
Open to-dos due today
routines todos today [OPTIONS]
| Option | Description |
|---|---|
--json |
Output as JSON |
routines todos today
todos overdue
Works with the app closed
Open to-dos whose due date has passed
routines todos overdue [OPTIONS]
| Option | Description |
|---|---|
--json |
Output as JSON |
routines todos overdue
todos show
Works with the app closed
Show one to-do in full, including its attached prompt
routines todos show [OPTIONS] <TODO>
| Argument | Description |
|---|---|
<TODO> |
To-do id, a unique id prefix, or a unique text substring |
| Option | Description |
|---|---|
--json |
Output as JSON |
routines todos show "board update"
todos add
Requires the Routines app running
Add a to-do (requires the Routines app to be running)
routines todos add [OPTIONS] <TEXT>...
| Argument | Description |
|---|---|
<TEXT>... |
What to do, e.g. routines todos add Buy milk |
| Option | Description |
|---|---|
--due <DUE> |
When it is due: a date, "today", "tomorrow", "+3d", or a weekday |
--priority <PRIORITY> |
How important it is: high, medium, or low |
--json |
Output as JSON |
routines todos add Buy oat milk
routines todos add "Draft the Q3 board update" --due friday --priority high
todos done
Requires the Routines app running
Mark a to-do done (requires the Routines app to be running)
routines todos done [OPTIONS] <TODO>
| Argument | Description |
|---|---|
<TODO> |
To-do id, a unique id prefix, or a unique text substring |
| Option | Description |
|---|---|
--json |
Output as JSON |
routines todos done "buy oat milk"
todos reopen
Requires the Routines app running
Mark a completed to-do open again (requires the Routines app to be running)
routines todos reopen [OPTIONS] <TODO>
| Argument | Description |
|---|---|
<TODO> |
To-do id, a unique id prefix, or a unique text substring |
| Option | Description |
|---|---|
--json |
Output as JSON |
routines todos reopen td-1a2b
todos edit
Requires the Routines app running
Change a to-do's text, due date, or priority (requires the Routines app to be running)
routines todos edit [OPTIONS] <TODO>
| Argument | Description |
|---|---|
<TODO> |
To-do id, a unique id prefix, or a unique text substring |
| Option | Description |
|---|---|
--text <TEXT> |
New text |
--due <DUE> |
New due date: a date, "today", "tomorrow", "+3d", or a weekday |
--clear-due |
Remove the due date |
--priority <PRIORITY> |
New priority: high, medium, or low |
--clear-priority |
Remove the priority |
--json |
Output as JSON |
routines todos edit "board update" --due 2026-07-20 --priority medium
routines todos edit "board update" --clear-due
todos prompt
Printing works with the app closed; --set, --generate, and --clear need the app running
Print a to-do's attached prompt, or change it with a flag
routines todos prompt [OPTIONS] <TODO>
| Argument | Description |
|---|---|
<TODO> |
To-do id, a unique id prefix, or a unique text substring |
| Option | Description |
|---|---|
--set <SET> |
Replace the prompt with this text (requires the Routines app to be running) |
--clear |
Remove the attached prompt (requires the Routines app to be running) |
--generate |
Draft a new prompt from the to-do and recent notes, and attach it (requires the Routines app to be running) |
--json |
Output as JSON |
routines todos prompt "board update"
routines todos prompt td-1a2b --set "Draft the update"
routines todos prompt td-1a2b --generate
todos run
Requires the Routines app running
Run a to-do's attached prompt through the app's assistant (requires the Routines app to be running)
routines todos run [OPTIONS] <TODO>
| Argument | Description |
|---|---|
<TODO> |
To-do id, a unique id prefix, or a unique text substring |
| Option | Description |
|---|---|
--done |
Mark the to-do done once the run finishes |
--json |
Output as JSON |
routines todos run "board update"
routines todos run td-1a2b --done
Sends the to-do's attached prompt through the user's own assistant and prints the reply. It starts a real agent turn, so it can take minutes. It fails when the to-do has no prompt yet.
todos delete
Requires the Routines app running
Delete a to-do (requires the Routines app to be running)
routines todos delete [OPTIONS] <TODO>
| Argument | Description |
|---|---|
<TODO> |
To-do id, a unique id prefix, or a unique text substring |
| Option | Description |
|---|---|
--force |
Skip the confirmation prompt |
--json |
Output as JSON |
routines todos delete "board update" --force
Email, calendar, Slack, and tools
Reach Gmail, Google Calendar, and Slack through the app's connectors, and call any tool the app exposes. These need the app running with the service connected.
email search
Requires the Routines app running
Search messages with a Gmail query (default: newer_than:1d)
routines email search [OPTIONS] [QUERY]
| Argument | Description |
|---|---|
[QUERY] |
Gmail search query, e.g. "from:boss@co.com is:unread" |
| Option | Description |
|---|---|
--limit <LIMIT> |
Maximum number of messages (1-20) [default: 10] |
--account <ACCOUNT> |
Only this inbox, by account email (default: all connected inboxes) |
--json |
Output as JSON |
routines email search "is:unread"
routines email search "invoice" --account finance@company.com
With no query it defaults to newer_than:1d. Results include Gmail message ids and attachment ids for chaining into email attachment.
email send
Requires the Routines app running
Send an email through the app's Gmail connector
routines email send [OPTIONS] --to <TO> --subject <SUBJECT> --body <BODY>
| Option | Description |
|---|---|
--to <TO> |
Recipient email address |
--subject <SUBJECT> |
Subject line |
--body <BODY> |
Plain-text body |
--cc <CC> |
CC recipient (repeatable) |
--bcc <BCC> |
BCC recipient (repeatable) |
--attach <ATTACH> |
Absolute file path to attach (repeatable, each ≤ 25 MB) |
--account <ACCOUNT> |
Send from this account, by account email |
--json |
Output as JSON |
routines email send --to a@b.com --subject "Status" --body "All green."
routines email send --to a@b.com --subject "Invoices" --body "Attached." \
--attach /Users/me/Downloads/invoice.pdf
This sends from the user's real account. --cc, --bcc, and --attach are repeatable; attachments are absolute file paths, each at most 25 MB.
email attachment
Requires the Routines app running
Download an email attachment to a local folder
routines email attachment [OPTIONS]
| Option | Description |
|---|---|
--message-id <MESSAGE_ID> |
Gmail message id (from email search); or use --query instead |
--attachment-id <ATTACHMENT_ID> |
Gmail attachment id (from email search) |
--query <QUERY> |
Gmail search query to find the message, e.g. "invoice newer_than:30d" |
--pattern <PATTERN> |
Filename substring or extension to match, e.g. ".pdf" or "invoice" |
--output <OUTPUT> |
Where to save: "downloads" (default), "documents", "desktop", or an absolute path |
--account <ACCOUNT> |
Only this inbox, by account email |
--json |
Output as JSON |
routines email attachment --query "invoice newer_than:30d" --pattern ".pdf"
routines email attachment --message-id 19eb62a4 --attachment-id ANGjdJ...
calendar today
Requires the Routines app running
Today's events
routines calendar today [OPTIONS]
| Option | Description |
|---|---|
--account <ACCOUNT> |
Only this calendar, by account email |
--json |
Output as JSON |
routines calendar today
calendar week
Requires the Routines app running
The next 7 days
routines calendar week [OPTIONS]
| Option | Description |
|---|---|
--account <ACCOUNT> |
Only this calendar, by account email |
--json |
Output as JSON |
routines calendar week
slack read
Requires the Routines app running
Recent messages from connected channels
routines slack read [OPTIONS]
| Option | Description |
|---|---|
--channel <CHANNEL> |
Specific channel IDs (defaults to connected channels) |
--limit <LIMIT> |
Messages per channel [default: 5] |
--json |
Output as JSON |
routines slack read
routines slack read --channel C0123456789 --limit 10
tools list
Requires the Routines app running
List every tool the Routines app exposes, with input schemas
routines tools list [OPTIONS]
| Option | Description |
|---|---|
--json |
Output as JSON |
routines tools list
Despite what the help text implies, tools list connects to the running app; there is no offline fallback.
tools call
Requires the Routines app running
Call a tool by name with JSON arguments
routines tools call [OPTIONS] <NAME>
| Argument | Description |
|---|---|
<NAME> |
Tool name (from routines tools list) |
| Option | Description |
|---|---|
--args <ARGS> |
Tool arguments as a JSON object, e.g. '{"query": "is:unread"}' |
--json |
Output as JSON |
routines tools call get_gmail_messages --args '{"query": "is:unread"}'
Claude Code sessions
Start Claude Code in a terminal or in the browser, drive a goal to completion, and see what is running.
claude terminal
Requires the Routines app running
Open a Claude Code session in your terminal
routines claude terminal [OPTIONS] [PROMPT]
| Argument | Description |
|---|---|
[PROMPT] |
Prompt to start the session with |
| Option | Description |
|---|---|
--dir <DIR> |
Folder to start in (defaults to the one set in Settings) |
--tab |
Open a tab instead of a new window, where the terminal supports it |
routines claude terminal
routines claude terminal "review the diff" --dir ~/code --tab
claude browser
Requires the Routines app running
Send a prompt to Claude in the browser
routines claude browser [OPTIONS] <PROMPT>
| Argument | Description |
|---|---|
<PROMPT> |
Prompt to send |
| Option | Description |
|---|---|
--url <URL> |
Page to open first |
--open-panel |
Open the Claude side panel first, in browsers where it is a blind toggle with no readable state. Ignored for Dia, which reports whether its Claude session view is open and is opened for you |
routines claude browser "summarize this page" --url https://example.com
Read the output: Sent to <browser>. ... means the prompt was read back out of Claude's composer before submitting. Submitted to <browser>, not fully verified: ... with a Verify: <path> screenshot means nothing could be read back, so check the screenshot before reporting success.
claude sessions
Works with the app closed
List the Claude Code sessions running on this Mac
routines claude sessions [OPTIONS]
| Option | Description |
|---|---|
--json |
Output as JSON |
routines claude sessions --json
goal
Requires the Routines app running
Open a Claude Code session that keeps working until a goal is done
routines goal [OPTIONS] [GOAL]...
| Argument | Description |
|---|---|
[GOAL]... |
The goal, in plain words (quotes optional) |
| Option | Description |
|---|---|
--dir <DIR> |
Folder to start in (defaults to the one set in Settings) |
--tab |
Open a tab instead of a new window, where the terminal supports it |
routines goal "get approval for gmail.send in Google API services" --tab
Agent integration
Wire the CLI into AI coding agents: print setup docs, serve MCP, or install the agent skill.
agent-docs
Works with the app closed
Print setup instructions and a CLAUDE.md snippet for AI coding agents
routines agent-docs
routines agent-docs
mcp
Works with the app closed
Start the stdio MCP server for AI agents (Claude Code, Claude Desktop)
routines mcp
routines mcp
skill
Works with the app closed
Print or install the AI agent skill for using Routines
routines skill [OPTIONS]
| Option | Description |
|---|---|
--install <INSTALL> |
Install the skill into a directory. Creates <path>/use-routines/SKILL.md |
routines skill
routines skill --install ~/.claude/skills
Troubleshooting
"Requires the Routines app to be running." The command you ran talks to
the app over its local socket. Open the app (open -a Routines) and run the
command again.
A read fails with no such column: verify_output (or another missing
column). The routines binary on your PATH is newer than the database schema
of the installed app: a newer copy sits earlier in your PATH than the one the
app linked, or the app was updated but has not run since. Every command that
reads the database fails the same way until the versions agree. Check
which routines and routines --version against the app's version, remove
the newer copy, or open the updated app once so it migrates the database.
claude browser reports the browser did not come to the front. Bring the
browser forward once and retry. The command drives the browser through
Accessibility, which needs the window frontmost.
A connector command answers that the service is not connected. Connect
Gmail, Google Calendar, or Slack in the app first, then check with
routines connectors.
For AI agents
Three commands wire Routines into coding agents. routines skill --install
installs the agent skill (a versioned reference the binary carries) into a
skills directory. routines agent-docs prints setup instructions and a
CLAUDE.md snippet. routines mcp starts a stdio MCP server so Claude Code or
Claude Desktop can call Routines as tools. The skill document ships inside
the binary itself, so it always matches the CLI it came with.