Setup guide · Tools and services
Run Temporal locally
A local Temporal dev server with its Web UI, plus a hello-world worker and workflow in TypeScript or Python that you can watch run.
Temporal runs durable workflows: code whose progress is recorded event by event, so it survives crashes, retries failed steps and can wait for days. Exercises on durable agents and long-running pipelines use it. Locally you need two things: the Temporal CLI, whose dev server is a complete Temporal Service in one process, and an SDK to write a worker (the process that runs your code) and a workflow. Everything here runs on your machine and costs nothing.
Before you start
- macOS, Linux or Windows.
- For TypeScript: Node.js 20 or newer. For Python: uv.
- Ports 7233 (the Temporal Service) and 8233 (the Web UI) free.
1. Install the Temporal CLI
macOS (and Linux with Homebrew)
brew install temporalLinux and Windows
Download the archive for your OS and CPU (amd64 or arm64) from the CLI setup page, for example https://temporal.download/cli/archive/latest?platform=linux&arch=amd64. Extract it and put the binary on your PATH:
sudo mv temporal /usr/local/binOn Windows, add the folder containing temporal.exe to your PATH. Check with temporal --version.
2. Start the dev server
Leave this running in its own terminal:
temporal server start-devThe Temporal Service listens on localhost:7233 and the Web UI is at http://localhost:8233. It creates the default namespace and keeps everything in memory, so history is gone when you stop it. To keep it between restarts, pass a database file:
temporal server start-dev --db-filename temporal.db3. Run a TypeScript worker and workflow
Scaffold the official hello-world sample:
npx @temporalio/create@latest ./hello-temporal --sample hello-world
cd hello-temporalIt contains an activity (greet, the step that does real work), a workflow (example, which calls it), a worker on the hello-world task queue and a client that starts the workflow. Start the worker in a second terminal and keep it running:
npm run startStart a workflow from a third terminal:
npm run workflowStarted workflow workflow-n7arf4s4mRgj6Mz4ZaCBo
Hello, Temporal!The sample uses npm scripts and ts-node. To add Temporal to your own project instead, install @temporalio/client, @temporalio/worker and @temporalio/workflow.
4. Run a Python worker and workflow
uv init hello-temporal-py
cd hello-temporal-py
uv add temporalioCreate the activity and the workflow. Workflow code must be deterministic, so the activity import is passed through the workflow sandbox:
from temporalio import activity
@activity.defn
async def greet(name: str) -> str:
return f"Hello {name}"from datetime import timedelta
from temporalio import workflow
with workflow.unsafe.imports_passed_through():
from activities import greet
@workflow.defn
class SayHelloWorkflow:
@workflow.run
async def run(self, name: str) -> str:
return await workflow.execute_activity(
greet,
name,
schedule_to_close_timeout=timedelta(seconds=10),
)The worker polls a task queue and runs whatever lands there; the starter puts a workflow on it:
import asyncio
from temporalio.client import Client
from temporalio.worker import Worker
from activities import greet
from workflows import SayHelloWorkflow
async def main():
client = await Client.connect("localhost:7233")
worker = Worker(
client,
task_queue="my-task-queue",
workflows=[SayHelloWorkflow],
activities=[greet],
)
print("Worker started.")
await worker.run()
if __name__ == "__main__":
asyncio.run(main())import asyncio
import uuid
from temporalio.client import Client
async def main():
client = await Client.connect("localhost:7233")
result = await client.execute_workflow(
"SayHelloWorkflow",
"Temporal",
id=f"say-hello-workflow-{uuid.uuid4()}",
task_queue="my-task-queue",
)
print("Workflow result:", result)
if __name__ == "__main__":
asyncio.run(main())Run the worker in one terminal and the starter in another:
uv run worker.pyuv run starter.pyWorkflow result: Hello TemporalCheck it works
List executions from any terminal:
temporal workflow list Status WorkflowId Type StartTime
Completed say-hello-workflow-1799e219-37ba-44d0-a535-f73b1c11b64a SayHelloWorkflow nowtemporal workflow show --workflow-id <id> prints the event history (workflow started, activity scheduled, started and completed, workflow completed) and the result. The same history is in the Web UI at http://localhost:8233: click the workflow ID to see each event, its input and its output.
Troubleshooting
connection refused on localhost:7233. The dev server isn't running, or it's in a terminal you closed. Start temporal server start-dev again.
The starter hangs and never prints a result. No worker is polling that task queue. Start the worker, and check that the worker and starter use the same queue name (hello-world in the TypeScript sample, my-task-queue in the Python one).
Port 8233 or 7233 already in use. Another dev server is still running. Stop it, or move the UI with temporal server start-dev --ui-port 8080.
Workflows from yesterday are gone. The dev server is in-memory by default. Use --db-filename temporal.db.
Going further
- Temporal Cloud is the hosted service for production. You don't need it for any exercise; the dev server behaves the same for learning.
- Python with uv and Node.js, pnpm and TypeScript
- OpenRouter or a local model?, for workflows whose activities call a model
- Trace LLM calls with OpenTelemetry and Langfuse
Sources
- Set up your local with the TypeScript SDKDocs · TemporalInstalling the CLI, `temporal server start-dev`, and scaffolding the hello-world sample.
- Set up your local with the Python SDKDocs · TemporalThe activity, workflow, worker and starter files this page uses.
- Temporal CLI setupDocs · TemporalDownload links per OS, default ports and `start-dev` flags such as `--db-filename`.
- Temporal CLI workflow commandsDocs · Temporal`temporal workflow list`, `show` and `describe` for inspecting executions.