Loren 🤓
Posted on April 27, 2023
In the Server 1.20 release we announced a new Temporal CLI, and we also released an interview and blog post with more info about it and its history.
The tl;dr is we combined our efforts on:
- The
next
version oftctl
, our old CLI temporalite
to create a single temporal
command-line tool that lets you both:
- run a development version of the Server
- interact with the Server
We recommend switching to temporal
for development and testing, and recommend using it for production scripts once we release v1 (coming soon). We will continue supporting tctl
for two more Server releases (through 1.22
).
In this post, you’ll learn how to use temporal
.
Contents:
Installing
cURL
curl -sSf https://temporal.download/cli.sh | sh
Homebrew
brew install temporal
Manual
You can also manually download, extract, and add to PATH the latest binary for your CPU architecture.
Running the Server
temporal server start-dev
This:
- starts the Server on
localhost:7233
- runs the Web UI at http://localhost:8233
By default, it doesn’t persist your data—if you start a Workflow, Ctrl-C, and run the command again, your Workflow will be gone.
If you'd like your Workflows to be saved, use the --db-filename
flag:
temporal server start-dev --db-filename temporal.db
Interacting with the Server
In another terminal, you can run commands to interact with the Server. This command starts a Workflow:
$ temporal workflow start \
--task-queue hello-world \
--type MyWorkflow \
--workflow-id 123 \
--input 456
Running execution:
WorkflowId 123
RunId 357074e4-0dd8-4c44-8367-d92536dd0943
Type MyWorkflow
Namespace default
TaskQueue hello-world
Args [456]
The shorthand options are:
temporal workflow start -t hello-world --type MyWorkflow -w 123 -i 456
You can also list and describe Workflows:
$ temporal workflow list
Status WorkflowId Name StartTime
Running 123 MyWorkflow 14 seconds ago
$ temporal workflow describe --workflow-id 123
{
"executionConfig": {
"taskQueue": {
"name": "hello-world",
"kind": "Normal"
},
"workflowExecutionTimeout": "0s",
"workflowRunTimeout": "0s",
"defaultWorkflowTaskTimeout": "10s"
},
"workflowExecutionInfo": {
"execution": {
"workflowId": "123",
"runId": "357074e4-0dd8-4c44-8367-d92536dd0943"
},
"type": {
"name": "MyWorkflow"
},
"startTime": "2023-04-15T06:42:31.191137Z",
"status": "Running",
"historyLength": "2",
"executionTime": "2023-04-15T06:42:31.191137Z",
"memo": {
},
"autoResetPoints": {
},
"stateTransitionCount": "1"
},
"pendingWorkflowTask": {
"state": "Scheduled",
"scheduledTime": "2023-04-15T06:42:31.191173Z",
"originalScheduledTime": "2023-04-15T06:42:31.191173Z",
"attempt": 1
}
}
When listing, you can get more Workflow fields and output in JSON:
$ temporal workflow list --fields long --output json
[
{
"execution": {
"workflow_id": "123",
"run_id": "357074e4-0dd8-4c44-8367-d92536dd0943"
},
"type": {
"name": "MyWorkflow"
},
"start_time": "2023-04-15T06:42:31.191137Z",
"status": 1,
"execution_time": "2023-04-15T06:42:31.191137Z",
"memo": {},
"task_queue": "hello-world"
}
]
Filter out just the type with jq:
$ temporal workflow list --fields long -o json | jq '.[].type.name'
"OtherWorkflow"
"MyWorkflow"
"MyWorkflow"
And count how many Workflows of each type you have:
$ temporal workflow list --fields long -o json | jq '.[].type.name' | uniq -c
1 "OtherWorkflow"
2 "MyWorkflow"
For a list of common commands, see our CLI cheatsheet.
To see what else you do to Workflows, run:
$ temporal workflow
NAME:
temporal workflow - Operations that can be performed on Workflows.
COMMANDS:
start Starts a new Workflow Execution.
execute Start a new Workflow Execution and prints its progress.
describe Show information about a Workflow Execution.
list List Workflow Executions based on a Query.
show Show Event History for a Workflow Execution.
query Query a Workflow Execution.
stack Query a Workflow Execution with __stack_trace as the query type.
signal Signal Workflow Execution by Id or List Filter.
count Count Workflow Executions (requires ElasticSearch to be enabled).
cancel Cancel a Workflow Execution.
terminate Terminate Workflow Execution by Id or List Filter.
delete Deletes a Workflow Execution.
reset Resets a Workflow Execution by Event Id or reset type.
reset-batch Reset a batch of Workflow Executions by reset type (LastContinuedAsNew), FirstWorkflowTask), LastWorkflowTask
trace Trace progress of a Workflow Execution and its children.
help, h Shows a list of commands or help for one command
And here are all the top-level commands:
$ temporal
NAME:
temporal - Temporal command-line interface and development server
USAGE:
temporal [global options] command [command options] [arguments...]
VERSION:
0.8.0 (server 1.20.1) (ui 2.13.3)
COMMANDS:
server Commands for managing the Temporal Server.
workflow Operations that can be performed on Workflows.
activity Operations that can be performed on Workflow Activities.
task-queue Operations performed on Task Queues.
schedule Operations performed on Schedules.
batch Operations performed on Batch jobs.
operator Operations performed on the Temporal Server.
env Manage environmental configurations on Temporal Client.
completion Output shell completion code for the specified shell (zsh, bash).
help, h Shows a list of commands or help for one command
You can read more about each by running temporal <command>
or reading the CLI docs.
Environments
So far, the CLI has been talking to the Server at the default address, localhost:7233
. To talk to another Server, like a production namespace on Temporal Cloud:
- Create an environment named
prod
. - Pass
--env prod
to commands, liketemporal workflow list --env prod
.
To create a new environment, start setting its properties:
temporal env set prod.namespace production.f45a2
temporal env set prod.address production.f45a2.tmprl.cloud:7233
temporal env set prod.tls-cert-path /temporal/certs/prod.pem
temporal env set prod.tls-key-path /temporal/certs/prod.key
Check that you set them correctly:
$ temporal env get prod
address production.f45a2.tmprl.cloud:7233
namespace production.f45a2
tls-cert-path /temporal/certs/prod.pem
tls-key-path /temporal/certs/prod.key
If they’re correct, then this shouldn’t log a connection error:
$ temporal workflow list --env prod
For the full list of properties you can set, see the below options:
$ temporal env set -h
OPTIONS:
Client Options:
--address value The host and port (formatted as host:port) for the Temporal Frontend Service. [$TEMPORAL_CLI_ADDRESS]
--codec-auth value Sets the authorization header on requests to the Codec Server. [$TEMPORAL_CLI_CODEC_AUTH]
--codec-endpoint value Endpoint for a remote Codec Server. [$TEMPORAL_CLI_CODEC_ENDPOINT]
--context-timeout value An optional timeout for the context of an RPC call (in seconds). (default: 5) [$TEMPORAL_CONTEXT_TIMEOUT]
--env value Name of the environment to read environmental variables from. (default: "default")
--grpc-meta value [ --grpc-meta value ] Contains gRPC metadata to send with requests (format: key=value). Values must be in a valid JSON format.
--namespace value, -n value Identifies a Namespace in the Temporal Workflow. (default: "default") [$TEMPORAL_CLI_NAMESPACE]
--tls-ca-path value Path to server CA certificate. [$TEMPORAL_CLI_TLS_CA]
--tls-cert-path value Path to x509 certificate. [$TEMPORAL_CLI_TLS_CERT]
--tls-disable-host-verification Disables TLS host name verification if already enabled. (default: false) [$TEMPORAL_CLI_TLS_DISABLE_HOST_VERIFICATION]
--tls-key-path value Path to private certificate key. [$TEMPORAL_CLI_TLS_KEY]
--tls-server-name value Provides an override for the target TLS server name. [$TEMPORAL_CLI_TLS_SERVER_NAME]
Display Options:
--color value when to use color: auto, always, never. (default: "auto")
For example, to set --codec-endpoint
, you would do:
$ temporal env set prod.codec-endpoint localhost:3000
Aliases
If you like aliases, here’s what I have in my ~/.bash_profile
:
alias t='temporal'
alias tw='temporal workflow'
alias ts='temporal server start-dev'
alias tsdb='temporal server start-dev --db-filename ~/temporal.db'
# send process to background so you can continue using the terminal
alias tsbg='temporal server start-dev &> /dev/null & disown'
You can also set up auto-completion for zsh or bash.
Upgrading
If you’re moving from tctl
, here are the major changes to be aware of:
Global changes
- New pagination mechanism with OS level tools such as
less
ormore
. Controlled by--pager
or$PAGER
. details - Most commands can format the output as a table or JSON using the
--output
option. details - You can limit the number of items when listing workflows, namespaces, etc. with, e.g.
--limit 10
. - DateTime formatting. details
- All command and flag names now use hyphen
-
as delimiter instead of underscore_
. details -
--color
option to choose when to enable/disable output coloring. Adds JSON coloring by default in TTY. details -
env
feature to manage CLI environments and change CLI options defaults. details - Updated the semantics of the commands and flags for consistency.
- All global flags are moved under each command.
Specific changes
-
namespace
,search-attribute
, andcluster
former top-level commands are now undertemporal operator
(these are meant for self-hosted Clusters, not Temporal Cloud). - Some commands are renamed:
namespace register
➡️namespace create
,search-attribute add
➡️search-attribute create
- Added new command
server start-dev
!
Future
0.8.0
is the current version, and we have just a few issues left before the 1.0 release. We are following semantic versioning, so after the 1.0 release, we won’t change or remove commands or arguments until 2.0.
Here is the list of feature requests that we and the community have submitted. We would value any additions you have, and it also helps us prioritize if you give the things you want a 👍 emoji upvote! We also welcome contributions—if you’re interested in improving the CLI, comment on the relevant issue with your plans for (or questions about) a PR. Another improvement we’re discussing is being able to use our Cloud CLI commands in the main CLI so that you can do commands like temporal cloud namespace create
.
Posted on April 27, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.