{"id":30351405,"url":"https://github.com/phuongdnguyen/temporal-workflow-debugger","last_synced_at":"2025-12-30T16:18:08.667Z","repository":{"id":308709294,"uuid":"1024246569","full_name":"phuongdnguyen/temporal-workflow-debugger","owner":"phuongdnguyen","description":"A debugger for Temporal.io workflows","archived":false,"fork":false,"pushed_at":"2025-08-15T10:48:50.000Z","size":9276,"stargazers_count":5,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-15T11:29:36.965Z","etag":null,"topics":["debugger","debugger-extension","jetbrains","temporalio","vscode-extension"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phuongdnguyen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-22T12:01:36.000Z","updated_at":"2025-08-15T10:48:41.000Z","dependencies_parsed_at":"2025-08-07T13:21:37.327Z","dependency_job_id":null,"html_url":"https://github.com/phuongdnguyen/temporal-workflow-debugger","commit_stats":null,"previous_names":["phuongdnguyen/temporal-workflow-debugger"],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/phuongdnguyen/temporal-workflow-debugger","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phuongdnguyen%2Ftemporal-workflow-debugger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phuongdnguyen%2Ftemporal-workflow-debugger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phuongdnguyen%2Ftemporal-workflow-debugger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phuongdnguyen%2Ftemporal-workflow-debugger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phuongdnguyen","download_url":"https://codeload.github.com/phuongdnguyen/temporal-workflow-debugger/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phuongdnguyen%2Ftemporal-workflow-debugger/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271073389,"owners_count":24694538,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-18T02:00:08.743Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["debugger","debugger-extension","jetbrains","temporalio","vscode-extension"],"created_at":"2025-08-18T23:02:07.373Z","updated_at":"2025-08-18T23:03:37.737Z","avatar_url":"https://github.com/phuongdnguyen.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"docs/images/logo.svg\" alt=\"Temporal Debugger Logo\" width=\"200\"\u003e\n\n\u003ca href=\"https://marketplace.visualstudio.com/items?itemName=phuongdnguyen.temporal-workflow-debugger\"\u003e\u003cimg src=\"https://img.shields.io/badge/Install%20from%20VS%20Code%20Marketplace-007ACC?logo=visual-studio-code\u0026logoColor=white\" alt=\"Install from VS Code Marketplace\"\u003e\u003c/a\u003e\n[![Go Replayer](https://pkg.go.dev/badge/github.com/phuongdnguyen/temporal-workflow-debugger/replayer-adapter-go.svg)](https://pkg.go.dev/github.com/phuongdnguyen/temporal-workflow-debugger/replayer-adapter-go)\n[![Python Replayer](https://badge.fury.io/py/temporal-replayer-adapter-python.svg)](https://badge.fury.io/py/temporal-replayer-adapter-python)\n[![Typescript Replayer](https://badge.fury.io/js/@phuongdnguyen%2Freplayer-adapter-nodejs.svg)](https://badge.fury.io/js/@phuongdnguyen%2Freplayer-adapter-nodejs)\n\n## Introduction\nTLDR: watch the [demo](https://www.youtube.com/watch?v=8XKKz0iotow\u0026t=50s).\n\nA comprehensive debugging solution that enables step-through debugging of [Temporal](https://github.com/temporalio/temporal) workflows. Unlike traditional debuggers that aren't aware of Temporal's execution model, this debugger provides a seamless development experience by allowing you to set breakpoints, inspect variables, and trace execution flow within your workflow code.\n\n## Why This Debugger?\n\nDebugging Temporal workflows has traditionally been challenging. Execution of a workflow is driven by history events rather than direct code execution. Workflow state is managed externally by the Temporal service, and the progress of a workflow depends on interaction between the Temporal server and a thick SDK that knows how to use history events to trigger the actual workflow code execution.\n\nThis debugger solves these challenges by leveraging the **workflow replayer** - it reconstructs workflow execution from Temporal's event history, allowing you to debug exactly what happened during the original execution.\n\n## Key Features\n\n- **Multi-language Support**: Works with Go, TypeScript/Node.js, and Python via adapters\n- **VS Code Extension**: Open a panel, load history, set event breakpoints, and replay with your adapter\n- **History Event-based Breakpoints**: Set breakpoints on specific workflow history events\n\n## Installation\n\n### Prerequisites\n\n1. **Install tdlv debugger** from [GitHub Release](https://github.com/phuongdnguyen/temporal-workflow-debugger/releases/tag/tdlv-v0.0.2)\n\n   Verify installation:\n   ```bash\n   tdlv --help\n   ```\n\n2. **Install language-specific dependencies**:\n\n   **Python**\n   ```bash\n   tdlv --lang=python --install\n   ```\n\n   **JavaScript/TypeScript**\n   ```bash\n   tdlv --lang=js --install\n   ```\n\n   **Go**\n   ```bash\n   tdlv --lang=go --install\n   ```\n\n### IDE Plugins\n\n**VS Code** : \n\u003ca href=\"https://marketplace.visualstudio.com/items?itemName=phuongdnguyen.temporal-workflow-debugger\"\u003e\u003cimg src=\"https://img.shields.io/badge/Install%20from%20VS%20Code%20Marketplace-007ACC?logo=visual-studio-code\u0026logoColor=white\" alt=\"Install from VS Code Marketplace\"\u003e\u003c/a\u003e\n\n### Replayers\n\n**Use language-specific replayers to debug your workflows:**\n- **Go**: [github.com/phuongdnguyen/temporal-workflow-debugger/replayer-adapter-go](https://pkg.go.dev/github.com/phuongdnguyen/temporal-workflow-debugger/replayer-adapter-go) [![Go Reference](https://pkg.go.dev/badge/github.com/phuongdnguyen/temporal-workflow-debugger/replayer-adapter-go.svg)](https://pkg.go.dev/github.com/phuongdnguyen/temporal-workflow-debugger/replayer-adapter-go)\n- **Python**: [temporal-replayer-adapter-python](https://pypi.org/project/temporal-replayer-adapter-python/) [![PyPI version](https://badge.fury.io/py/temporal-replayer-adapter-python.svg)](https://badge.fury.io/py/temporal-replayer-adapter-python)\n- **TypeScript**: [@phuongdnguyen/replayer-adapter-nodejs](https://www.npmjs.com/package/@phuongdnguyen/replayer-adapter-nodejs) [![npm version](https://badge.fury.io/js/@phuongdnguyen%2Freplayer-adapter-nodejs.svg)](https://badge.fury.io/js/@phuongdnguyen%2Freplayer-adapter-nodejs)\n\n## Usage\n\n### VS Code\n\n#### Quick Start\n\n1. **Install Extension**: Install from VS Code Marketplace\n2. **Follow Language Examples**:\n   - [TypeScript](./example/js/vscode-replayer.ts)\n   - [Go](./example/go/structured-workflow/replay-debug-ide-integrated/)\n   - [Python](./example/python/vscode-replay.py)\n3. **Open Panel**: Run `Temporal: Open Panel` (Cmd/Ctrl-Shift-P)\n4. **Load History**: Enter Workflow ID or choose history JSON file\n5. **Set Breakpoints**: Select history events to stop on\n6. **Debug**: Start replaying - execution pauses at breakpoints\n\n#### Server Configuration\n\nDefault connection: `localhost:7233`\n\nTo connect to different servers:\n- Open `SETTINGS` tab\n- Edit `Address` field\n- For TLS (Temporal Cloud): check box and select client cert/key\n\n### Debug setup\nTested language version\n- Go 1.19+.\n- NodeJS v22.17.0, Npm 10.9.2\n- Python 3.12.11\n\n\n#### TypeScript\n\nCreate a small `replayer.ts` in your project that runs the Tyepscript replayer adapter in IDE mode and registers your workflow function, for example:\n\n1. Install the replayer first:\n\n```\nnpm i @phuongdnguyen/replayer-adapter-nodejs --save\n```\n\n2. Install the debugger [tdlv](https://github.com/phuongdnguyen/temporal-workflow-debugger/releases/tag/tdlv-v0.0.2) and add it to PATH\n3. Verify tldv is installed in PATH\n\n```\ntdlv --help\nMissing required flags: -lang\n\nTdlv (Temporal delve) is a temporal workflow debugger\n\nUsage: tdlv [options]\n\n  -help\n        Tdlv (Temporal delve) is a temporal workflow debugger, provide ability to focus on user workflow code in debug sessions (alias: -h)\n  -install\n        auto-install missing language debuggers\n  -lang string\n        [required] language to use for the workflow, available options: [go, python, js]\n  -p int\n        port for remote debugging (default 60000)\n  -start\n        start debugger\n```\n\n4. Your entrypoint file should import the replayer adapter and your workflow:\n\n```typescript\nimport { exampleWorkflow } from \"./workflow\"\nimport { ReplayMode, replay } from \"@phuongdnguyen/replayer-adapter-nodejs\"\n\nasync function main() {\n  const opts = {\n    mode: ReplayMode.IDE,\n    workerReplayOptions: {\n      workflowsPath: require.resolve(\"./workflow.ts\"),\n    },\n  }\n\n  await replay(opts, exampleWorkflow)\n}\n\nif (require.main === module) {\n  main().catch((error) =\u003e {\n    console.error(\"Error:\", error)\n    process.exit(1)\n  })\n}\n```\n\n5. Open or create `.vscode/settings.json` and add the config field:\n\n```json\n{\n  \"temporal.replayerEntryPoint\": \"replayer.ts\"\n}\n```\n\n_Note that the file must be within your project directory so it can find `node_modules/`._\n\n#### Go\n\n1. Get the replayer code\n\n```\ngo get -u github.com/phuongdnguyen/temporal-workflow-debugger/replayer-adapter-go@latest\n```\n\n2. Create a small `main.go` in your project that runs the Go replayer adapter in IDE mode and registers your workflow function, for example:\n\n```go\npackage main\n\nimport (\n    \"go.temporal.io/sdk/worker\"\n    replayer_adapter_go \"github.com/phuongdnguyen/temporal-workflow-debugger/replayer-adapter-go\"\n    \"example/pkg/workflows\"\n)\n\nfunc main() {\n    replayer_adapter_go.SetReplayMode(replayer_adapter_go.ReplayModeIde)\n    err := replayer_adapter_go.Replay(replayer_adapter_go.ReplayOptions{\n        WorkerReplayOptions: worker.WorkflowReplayerOptions{DisableDeadlockDetection: true},\n    }, workflows.ExampleWorkflow)\n    if err != nil {\n        panic(err)\n    }\n}\n```\n\n3. Configure the extension:\n\n```json\n{\n  \"temporal.debugLanguage\": \"go\",\n  \"temporal.replayerEntrypoint\": \"main.go\"\n}\n```\n\n4. Run \"Temporal: Open Panel\"\n5. Enter a Workflow Id or choose a history JSON file\n6. Click `Load History`\n7. Select history events that you want the workflow to be stopped on\n8. Hit `Start debug session`\n\n#### Python\n\n1. Make sure your Python environment has the required dependencies installed:\n\n```bash\npip install temporalio replayer-adapter-python\n```\n\n2. Create a small script (e.g. `replayer.py`) that uses the Python replayer adapter in IDE mode and references your workflow:\n\n```python\nimport asyncio\nfrom replayer_adapter_python.replayer import (\n    ReplayMode, ReplayOptions, set_replay_mode, replay\n)\nfrom workflow import UserOnboardingWorkflow\n\nasync def main():\n    \"\"\"Run ide examples\"\"\"\n    try:\n        # Set up ide mode\n        set_replay_mode(ReplayMode.IDE)\n\n        # Create replay options\n        opts = ReplayOptions(\n            worker_replay_options={},\n        )\n        result = await replay(opts, UserOnboardingWorkflow)\n        print(f\"Result: {result}\")\n    except Exception as e:\n        print(f\"Replay failed: {e}\")\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n\n3. Configure the extension:\n\n```json\n{\n  \"temporal.debugLanguage\": \"python\",\n  \"temporal.replayerEntryPoint\": \"replayer.py\"\n  // If you want use a custom python rather the one in PATH\n  // \"temporal.python\": \"/Your/path/to/python\"\n}\n```\n\n4. Run \"Temporal: Open Panel\"\n5. Enter a Workflow Id or choose a history JSON file\n6. Click `Load History`\n7. Select history events that you want the workflow to be stopped on\n8. Hit `Start debug session`\n\n\n## Architecture\n\n### Overview\n\nThe plugin consists of an IDE Debugging UI, service layer, and debugger (`tdlv`) for debugging Temporal workflows.\n\n### Components\n\n- **IDE Debugging UI**: Panel for history upload and set breakpoints.\n- **IDE Debugging Service**: Provide API for the Debugger to retrieve the uploaded history \u0026 breakpoints.\n- **Debugger (`tdlv`)**: Communicates with language debugger (think Delve, Js-Debug, Debugpy) to intercept debugging event. If a breakpoint is hit, the Debugger notifies the IDE Debugging Service to highlight the event that has its breakpoint hit.\n- **Adapter**: Adapter places sentinel breakpoints inside Temporal workflow/activity interceptors.\n\n### Architecture Diagram\n\n```\n┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐\n│   IDE Plugin    │    │   Serving Layer  │    │ Debugger Server │\n│                 │◄──►│   (tdlv)         │◄──►│   + Workflow    │\n│                 │    │                  │    │   Replayer      │\n└─────────────────┘    └──────────────────┘    └─────────────────┘\n        │                       │                       │\n        │              ┌────────▼────────┐              │\n        │              │IDE Plugin Server│              │\n        │              │ (Breakpoints +  │              │\n        └─────────────►│  History)       │◄─────────────┘\n                       └─────────────────┘\n```\n\nThe debugger consists of several integrated components:\n\n1. **IDE Plugin**: Provides the user interface, manages workflow history, and integrates with IDE debugging\n2. **Serving layer (`tdlv`)**: Intercepts debugging commands and enhances them with workflow-specific logic\n3. **Workflow Replayer**: Executes workflow code deterministically using Temporal's replayer\n4. **History Server**: Manages workflow event history and breakpoint state\n5. **Replayer Adapter Layer**: Connects the replay execution with the debugging infrastructure\n\n### Debug Flow\n\n1. User upload history JSON.\n2. User set event breakpoints.\n3. User start debugging session.\n4. Plugin launches `tdlv` process.\n\n### Design Decisions\n\nSome notable design decisions are:\n- Place sentinel breakpoints in workflow \u0026 activity interceptors\n- Intercept DAP stream to hide workflow \u0026 adapter code\n- For go delve-json rpc integration (used in Goland), re-use some of the logic in Delve to differentiate JSON-RPC and DAP based on the first byte.\n\n```mermaid\nsequenceDiagram\nDebug Client -\u003e\u003e Debugger API: Attach\nDebugger API -\u003e\u003e Router: Check header\nRouter -\u003e\u003e DAP Handler: Handle as DAP\nRouter -\u003e\u003e JSON RPC Handler: Handle as json rpc\nJSON RPC Handler --\u003e\u003e Router: \nDAP Handler --\u003e\u003e Router: \nRouter --\u003e\u003e Debugger API: \nDebugger API --\u003e\u003e Debug Client: Attached\n```\n\n## How it works\n\nThe debugger leverages Temporal's workflow replayer functionality to reconstruct execution from event history. When you debug a workflow:\n\n1. The replayer processes the workflow's event history deterministically\n2. Sentinel breakpoints are placed in workflow/activity interceptors via language-specific adapters\n3. The `tdlv` serving layer intercepts debugging commands and coordinates with your IDE\n4. When execution hits a breakpoint, the debugger pauses and allows inspection of the workflow state at that specific point in history\n\nThis approach provides accurate debugging of the exact execution that occurred, rather than a new execution that might behave differently.\n\n![1](./docs/images/1.jpg)\n![2](./docs/images/2.jpg)\n\n## Development Setup\n\n### Prerequisites\n\n- Clone repository\n- Build tdlv: `go build` in tdlv/\n- Build VS Code extension: see [vscode extension readme](./vscode-debugger-extension/README.md)\n\n### Project Structure\n\n- **tdlv/**: Intercept message from language debugger\n- **jetbrains-plugin/**: JetBrains Plugin (support Go)\n- **vscode-debugger-extension**: VS Code Extension (support Go, Python, Js/TS)\n- **replayer-adapter-go/**: Inject sentinel breakpoints for Temporal Go SDK\n- **replayer-adapter-python/**: Inject sentinel breakpoints for Temporal Python SDK\n- **replayer-adapter-nodejs/**: Inject sentinel breakpoints for Temporal TypeScript SDK\n- **example/**: Test workflows\n\n## Contributing\n\nThis project welcomes contributions. To contribute:\n\n- Fork and branch from main\n- Add tests for new functionality\n- Update documentation as needed\n- Submit PR with clear description of changes\n\nPlease see the individual component READMEs and documentation for development guidelines.\n\n## License\n\n[Apache 2.0](./LICENSE)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphuongdnguyen%2Ftemporal-workflow-debugger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphuongdnguyen%2Ftemporal-workflow-debugger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphuongdnguyen%2Ftemporal-workflow-debugger/lists"}