Skip to content
Development
Skill

/internal-dev-workbench

Spin up a portless + tmux dev session for the Workflow SDK that gives each git worktree isolated `<branch>.<name>.localhost` URLs for the Next.js workbench and the observability UI, plus a Claude statusline that surfaces those URLs. Use only when the user asks for a "portless

From plugin
workflow
2.5k6 skills1 agent1 command

Claude Code

$ npx -y skills add vercel/workflow --skill internal-dev-workbench --agent claude-code

SKILL.md

internal-dev-workbench.SKILL.md
name: internal-dev-workbench
description: Spin up a portless + tmux dev session for the Workflow SDK that gives each git worktree isolated `<branch>.<name>.localhost` URLs for the Next.js workbench and the observability UI, plus a Claude statusline that surfaces those URLs. Use only when the user asks for a "portless dev session", a "tmux dev layout for workflow", "worktree-isolated dev URLs", or wants to wire workflow dev URLs into the Claude statusline. Do not activate for the generic "start the dev server" / "run pnpm dev" task.
metadata:
  author: Pranay Prakash
  version: '0.2'

internal-dev-workbench

Bootstraps an opinionated 3-pane tmux session for end-to-end Workflow SDK development. Each pane is launched through [portless](https://github.com/aleclarson/portless) so URLs are stable and worktree-scoped (e.g. `https://<branch>.turbopack.localhost`), letting multiple worktrees run concurrently without port conflicts. A companion statusline script surfaces the active URLs in Claude Code's prompt.

This is **opt-in contributor tooling**. The repo's standard dev path (`pnpm dev` from a workbench, no portless) is unaffected.

Prerequisites

  • `tmux` installed
  • `portless` installed globally (`npm i -g portless` or via Homebrew). Verify with `portless --version`.
  • Repo bootstrapped: `pnpm install && pnpm build`. The first run on a fresh worktree must complete both before any dev server can start (the workbench apps depend on built workspace packages; without `pnpm build` you get `MODULE_NOT_FOUND` for `workflow`).
  • `WORKFLOW_PUBLIC_MANIFEST=1` is required on the dev server when running e2e tests against it (otherwise `/.well-known/workflow/v1/manifest.json` is gated).

Layout

With `main-vertical`, the dev server takes the left column; the right column stacks the observability UI on top of a scratchpad shell:

+----------------------+--------------------------+
|                      |  PANE_OBS: workflow web  |
|                      |  (observability UI       |
|  PANE_DEV: turbopack |   scoped to the          |
|  (Next.js dev)       |   workbench app)         |
|                      +--------------------------+
|                      |  PANE_SH: zsh scratchpad |
|                      |  (repo root, for build, |
|                      |   tests, e2e, git, etc.) |
+----------------------+--------------------------+

Setup

The session name **must** match the worktree's portless prefix (the basename of the current branch) so the statusline and any other tooling that derives the prefix from the branch can locate it. Always run `tmux ls` first to confirm there's no pre-existing session with that name; never kill an existing one.

Pane indices in tmux depend on `pane-base-index` (0 by default, 1 with the common dotfile override). To stay correct under either, capture each pane's ID at split time with `-P -F '#{pane_id}'` and use those IDs as targets:

REPO=/path/to/workflow--<worktree-suffix>
# Session name = basename of the branch (matches portless's subdomain prefix
# and the statusline's `tmux attach -t <prefix>` indicator). For branch
# `pgp/foo-bar` this resolves to `foo-bar`.
SESSION=$(git -C "$REPO" rev-parse --abbrev-ref HEAD)
SESSION="${SESSION##*/}"

# Create the session and capture the initial pane ID
PANE_DEV=$(tmux new-session -d -s "$SESSION" -c "$REPO" -P -F '#{pane_id}')
PANE_OBS=$(tmux split-window -h -t "$PANE_DEV" -c "$REPO" -P -F '#{pane_id}')
PANE_SH=$(tmux split-window -v -t "$PANE_OBS" -c "$REPO" -P -F '#{pane_id}')
tmux select-layout -t "$SESSION" main-vertical

# Pane DEV (left): Next.js turbopack workbench, with manifest exposed for e2e
tmux send-keys -t "$PANE_DEV" \
  'cd workbench/nextjs-turbopack && WORKFLOW_PUBLIC_MANIFEST=1 portless run --name turbopack pnpm dev' C-m

# Pane OBS (top-right): observability UI scoped to the workbench app
tmux send-keys -t "$PANE_OBS" \
  'cd workbench/nextjs-turbopack && portless run --name workflow-obs sh -c "pnpm workflow web --webPort \$PORT --noBrowser"' C-m

# Pane SH (bottom-right): scratchpad at repo root
tmux send-keys -t "$PANE_SH" 'echo "scratchpad: $(pwd)"' C-m

tmux attach -t "$SESSION"

Once both servers are ready, `portless list` shows the routes. With `portless run`, each linked worktree gets a unique branch-prefixed subdomain (e.g. `stepflow-test.turbopack.localhost`), so multiple worktrees coexist without changing config.

Why each piece

  • **`portless run --name <name>`** (instead of `portless <name> <cmd>`): `run` auto-detects git worktrees and prepends the sanitized branch name as a subdomain. The `--name` flag overrides the inferred base name while preserving the worktree prefix.
  • **`pnpm workflow web --webPort $PORT --noBrowser`** (instead of `pnpm dev` in `packages/web`): the bundled CLI starts the observability UI configured against the **current workbench app**, hydrating it with that project's local World data. Running `packages/web`'s own `dev` script gives you the UI but pointed at nothing.
  • **`sh -c '... --webPort $PORT'`**: portless's auto `--port` injection only triggers for known frameworks it can detect on the command line. When the command is a CLI wrapper (`pnpm workflow web`), wrap in `sh -c` and read `$PORT` (which portless always sets) explicitly.
  • **`WORKFLOW_PUBLIC_MANIFEST=1`** on the dev pane: required for e2e tests to fetch the workflow registry from the dev server.
  • **`-P -F '#{pane_id}'`**: makes the snippet correct regardless of the user's `pane-base-index` setting (defaults vary across configs).

Claude statusline integration

The skill ships a statusline helper at `skills/internal-dev-workbench/statusline.sh` that derives the worktree prefix from the current branch and emits a compact line:

 dev  ·   obs  ·   tmux attach -t <worktree-prefix>

The dev / obs labels (Nerd Font rocket / graph glyphs) are OSC 8 hyperlinks that are clickable in iTerm2, Kitty, WezTerm, Terminal.app, and Ghostty. Bold, underlined, bri

Read more
@vercel
Ships withworkflow

Workflow SDK: Build durable, reliable, and observable apps and AI Agents in TypeScript

2.5k6 skills1 agent
Get the whole plugin

Stars on GitHub

Momentum

stars in total
2.5k
Star history of vercel/workflow on GitHub, a chart by star-history.com

Other skills on workflow.

migrating-to-workflow-sdk

migrating-to-workflow-…

Migrates Temporal, Inngest, Trigger.dev, and AWS Step Functions workflows to the Workflow SDK. Use when porting Activities,…

@vercel@vercelInstall Skill
migrating-workflow-v4-to-v5

migrating-workflow-v4-…

Upgrades an app from Workflow SDK 4.x to 5.0. Use when bumping the `workflow` / `@workflow/*` dependencies to v5, or when hitting…

@vercel@vercelInstall Skill
migrating-world-v4-to-v5

migrating-world-v4-to-…

Upgrades a custom Workflow SDK World implementation from the v4 spec, or from a 5.0.0 beta, to the current v5 spec (spec version…

@vercel@vercelInstall Skill
workflow-init

workflow-init

Install and configure Vercel Workflow SDK before it exists in node_modules. Use when the user asks to "install workflow", "set up…

@vercel@vercelInstall Skill
workflow

workflow

Creates durable, resumable workflows using Vercel's Workflow SDK. Use when building workflows that need to survive restarts,…

@vercel@vercelInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills10d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react1d252k
@facebook@facebookInstall Skill

Questions about internal-dev-workbench.

Which coding agents can use internal-dev-workbench?
internal-dev-workbench installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.