Tooling
Write, validate, and visualize flows anywhere
Pipedown is a portable format — it doesn’t live inside start.chat. You can
write .pd files in your own editor, validate them in CI, visualize them as
diagrams, and even transpile them to TypeScript or Mastra workflows.
This page covers everything you need to work with pipedown outside of start.chat: the CLI, editor support, configuration, and syntax highlighting integrations. For how start.chat executes pipedown programs at runtime, see How it Runs.
CLI (@pipedown/cli)
The command-line tool for validating, visualizing, building, and generating code
from .pd files. Uses citty under the hood.
Terminal
pipedown validate [file]
Use this to catch syntax errors and structural issues before they hit production — works great as a CI gate.
Parses one .pd file or recursively scans cwd for all .pd files (skips
node_modules/ and dist/).
Checks performed:
- Parse errors (syntax)
- No steps found in flow (warning)
- Slash command missing action (error)
- Slash command with no message text (warning)
eachblock references a variable that doesn’t exist (warning)---separator at the very start or end (warning)
Exit code 1 when any issues are found, so it works in CI:
pipedown graph <file> [--format mermaid|html] [--open]
Use this to see the shape of a flow at a glance — especially helpful for
debugging complex parallel or each structures.
Converts a .pd file to a Mermaid graph TD diagram.
- Default format is
html— writes a self-contained HTML page to a temp file and opens it in the system browser --format mermaidprints raw Mermaid source to stdout--no-opensuppresses auto-open
Visual conventions: trigger as green stadium node, LLM steps purple, app steps
blue, separator as a barrier circle, parallel steps fan out directly, each
blocks as subgraphs.
pipedown generate --language <target> [--file <file>] [--outDir <dir>]
Use this to export your flows as real code — useful for migrating to another platform or running flows outside of start.chat entirely.
Transpiles .pd files to runnable code in a target language.
Targets:
typescript/ts— async functions wrappingPipedownRuntimecalls. Sequential steps becomeawait runtime.app(...), parallel blocks becomePromise.all,eachblocks becomeforloops.mastra— Mastra workflow DSL (createWorkflow/createStepfrom@mastra/core). App steps map tocreateStep, LLM steps to prompt steps, schedule triggers totrigger: { schedule: '...' }.
When --outDir is given, writes one file per input .pd file. Without it,
prints all generated output to stdout.
New targets can be added by implementing
(content: string, filePath: string) => string and registering in the
generators map.
pipedown build [--outDir dist]
Use this to pre-parse flows for deployment — feed the JSON AST into a custom runtime or a CI artifact.
Parses every .pd file in cwd recursively and writes one .json file per flow
to outDir/ (default: dist/). The JSON output is the parsed PipedownProgram
AST:
VSCode extension (pipedown-vscode)
Use this for first-class .pd editing in VSCode — syntax highlighting,
completions, and diagnostics without leaving your editor.
Registers .pd files as the pipedown language. Activates via
onLanguage:pipedown.
Features:
- Language registration:
.pdextension, aliasesPipedown,pipedown,pd - Syntax highlighting via TextMate grammar (
source.pipedown) - Markdown code block injection —
```pdfences in.mdfiles get highlighting too - LSP client connecting to
@pipedown/lspfor diagnostics, completions, hover
The extension uses vscode-languageclient with TransportKind.ipc to start the
LSP server in-process.
LSP (@pipedown/lsp)
Use this for editor-agnostic intelligence — any editor that speaks LSP (Neovim, Helix, Zed, etc.) gets diagnostics, completions, and hover info.
Implemented with vscode-languageserver. Server capabilities:
textDocumentSync: IncrementalcompletionProvider— trigger characters:.:"hoverProvider
Completions
Currently in progress — the completion logic is implemented in
@pipedown/core’s createCompletionProvider() (Monaco) and being ported to the
LSP. The Monaco provider (reference implementation) supports:
/at start of line — suggests all registered apps/app— suggests actions for that app with descriptionson— suggests apps that have eventson app.— suggests events for that app- Empty line — suggests starting patterns:
* /,/,---,each,every,on
Hover
In progress — planned to show action descriptions from the app registry on
hover over /app action tokens.
Diagnostics
The plumbing is in place (validateDocument fires on every content change) but
the check logic from pipedown validate hasn’t been ported yet.
Using the LSP standalone
For editors other than VSCode (Neovim, Helix, Zed, etc.), create a small wrapper:
The wrapper must use stdio transport — the VSCode extension uses IPC internally.
Configuration (pipedown.config.ts)
Drop a pipedown.config.ts at the root of your project and all CLI commands
will pick it up automatically. Flags override config values when both are
present.
| Field | Type | Default | Description |
|---|---|---|---|
include | string[] | all **/*.pd | Glob patterns for input |
exclude | string[] | none | Glob patterns to skip |
outDir | string | 'dist' | Output dir for build |
graph.format | 'svg' | 'png' | 'mermaid' | — | Graph output format |
graph.theme | 'dark' | 'light' | — | Graph color theme |
generate.languages | Array<{ name, outDir? }> | — | Code generation targets |
Syntax highlighting
Pipedown ships highlighting integrations for static sites (Shiki), in-browser editors (Monaco), and any editor that supports TextMate grammars.
Shiki (static / SSG)
Use this for docs sites and static rendering — drop in the grammar and
highlight .pd code blocks at build time.
pipedownLanguage is an array containing the grammar object with
id: 'pipedown' and aliases ['pd', 'pipedown'], derived from the TextMate
grammar.
Monaco (in-browser editor)
Use this for browser-based flow editors — gives you tokenization, completions, and theming out of the box.
registerPipedownLanguage wires up: Monarch tokenizer, language configuration
(/[^\s]+/ word pattern, no auto-closing pairs), completion provider (apps,
actions, events, keywords with / and space as trigger characters), and
pipedown-dark/pipedown-light themes.
configurePipedownApps replaces the entire registry (does not append). Call
it before registerPipedownLanguage or call it again to update completions at
runtime.
TextMate grammar
Located at packages/pipedown/src/pipedown.tmLanguage.json. Scope:
source.pipedown.
| Pattern | Scope |
|---|---|
# name: / ## desc | comment.line / string.unquoted |
# Title heading | entity.name.section |
--- separator | keyword.control |
every / on trigger | keyword.control |
name = variable block | entity.name.section |
each keyword + refs | keyword.control + entity.name.tag |
* parallel prefix | keyword.operator.parallel |
- sequential prefix | punctuation.definition.list |
/app slash + app name | entity.name.function |
/app action action name | entity.name.tag |
{{variable}} references | variable.other |
@mention references | entity.name.tag |
| Remaining text | string.unquoted |
The grammar is shared between the VSCode extension and the Shiki export. The extension also injects pipedown highlighting into Markdown fenced code blocks.
Example project
packages/pipedown-example shows a multi-flow project structure with everything
wired together:
Terminal