Help us improve
Share bugs, ideas, or general feedback.
From SeeFlow
Generates a validated SeeFlow flow with flow.json and node-sidecar files from a natural-language prompt. Routes inspection requests to /seeflow-lookup first and only activates when no matching flow exists.
npx claudepluginhub tuongaz/seeflowHow this skill is triggered — by the user, by Claude, or both
Slash command
/seeflow:seeflowThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Turn a natural-language prompt into a registered SeeFlow flow at `$repoPath/flows/<flowSlug>/flow.json` (skill-created projects default to `flowSlug: 'main'`), with node-attached content (scripts, detail.md, view.html) under `$repoPath/flows/<flowSlug>/nodes/<id>/`. Orchestrate five sub-agents and the `seeflow` CLI; never read the codebase directly, never author `seeflow.json` or `flow.json` by...
agents/seeflow-code-analyzer.mdagents/seeflow-node-planner.mdagents/seeflow-play-designer.mdagents/seeflow-status-designer.mdagents/seeflow-system-analyzer.mdreferences/cli.mdreferences/core-rules.mdreferences/learn-format.mdreferences/operations.mdreferences/phases/p0-preflight.mdreferences/phases/p1-discover.mdreferences/phases/p2-plan-nodes.mdreferences/phases/p3-scaffold.mdreferences/phases/p4-design-overlays.mdreferences/phases/p5-patch-overlays.mdreferences/phases/p6-validation.mdreferences/planner/examples.mdreferences/schema.mdreferences/tech/README.mdreferences/tech/_template.mdCreates p5.js generative art with seeded randomness, noise fields, and interactive parameter exploration. Use for algorithmic art, flow fields, or particle systems.
Share bugs, ideas, or general feedback.
Turn a natural-language prompt into a registered SeeFlow flow at $repoPath/flows/<flowSlug>/flow.json (skill-created projects default to flowSlug: 'main'), with node-attached content (scripts, detail.md, view.html) under $repoPath/flows/<flowSlug>/nodes/<id>/. Orchestrate five sub-agents and the seeflow CLI; never read the codebase directly, never author seeflow.json or flow.json by hand (projects:create writes both the manifest and the first flow envelope).
nodes:patch).flows:delete.flows:layout.(A project with no source tree is not an exclusion — it routes to the document branch at the Phase 0 input-source gate without asking.)
A host repo opts into seeflow by creating a <host>/.seeflow/ directory (the only place this skill introduces a .seeflow folder — the studio itself is path-agnostic). LEARN.md is shared across every project and flow in the host and lives at <host>/.seeflow/LEARN.md; each project lives in its own subdirectory beside it, with one folder per flow nested inside under flows/:
<host>/ ← the user's repo
.seeflow/ ← container, created by this skill
LEARN.md ← shared crib for this skill (host-wide, used by every project + flow)
<projectSlug>/ ← seeflow project root — passed to projects:create --path
seeflow.json ← manifest (project metadata + flow registry)
flows/<flowSlug>/ ← per-flow folder (one per flows[] entry)
flow.json ← envelope + nodes/connectors
style.json ← layout/visuals (managed by `flows:layout`)
nodes/<id>/ ← per-node sidecar files (detail.md, view.html, scripts/)
.tmp/ ← per-flow scratch ($SEEFLOW_TMP)
state/ ← per-flow runtime script state
Skill-created projects default to a single flow with flowSlug: 'main'; subsequent flows in the same project are added via flows:create --project <projectSlug> --flow <flowSlug>.
Always call seeflow projects:create --path "$repoPath" --name "..." — the CLI writes both seeflow.json and flows/main/flow.json in one shot. Inside --path, every CLI / file reference is relative to that project root — never re-prefix with .seeflow/.
~/.seeflow/ (user-home) is a separate, unrelated directory that holds the studio's global registry / config / pid files; leave its paths verbatim wherever they appear.
$PWD); ~/.seeflow/config.json (optional studio host:port).<project>/flow.json (skip the creation path if already present — fall back to register --flow flow.json).$learnPath ($PWD/.seeflow/LEARN.md) — persistent crib sheet shared across every project + flow in this host repo, written by prior /seeflow runs. Read before Phase 1. Format: references/learn-format.md.| Variable | Resolution |
|---|---|
$STUDIO_URL | SEEFLOW_STUDIO_URL → ~/.seeflow/config.json port → http://localhost:4321. |
$projectSlug | The first segment of the combined slug in the projects:create response. The response is { ok, id, slug } where slug is "<projectSlug>/<flowSlug>" (e.g. "order-pipeline/main") — split on / and take [0]. Authoritative for every follow-up --project call. The studio derives it as slugify(--name) (e.g. --name "Order Pipeline" → order-pipeline) — not from the planner's slug field, which may differ. Never reuse the planner's slug as --project; always reassign $projectSlug from the response slug (see phases/p3-scaffold.md § 1). |
$flowSlug | the flow id within the project — the second segment of the projects:create response slug (slug.split('/')[1]). Defaults to 'main' for skill-created projects; subsequent flows:create calls take arbitrary lowercase-kebab ids matching ^[a-z0-9][a-z0-9-]*$. |
$repoPath | $PWD/.seeflow/<planner-slug> — the directory passed to projects:create --path. This is just a path; the planner's slug names the folder. It does not have to equal $projectSlug (the registry resolves --project calls by slug, and stores repoPath independently). |
$learnPath | $PWD/.seeflow/LEARN.md — shared across every project + flow in the host repo. Lives next to the project folders, never inside one. |
$SEEFLOW_TMP | $repoPath/flows/$flowSlug/.tmp/ — per-flow scratch directory. Full lifecycle in §"Scratch files & cleanup" below. |
seeflow | Locally installed seeflow binary if command -v seeflow >/dev/null 2>&1; otherwise npx -y @tuongaz/seeflow@latest. Resolve once at session start (e.g. `SEEFLOW="$(command -v seeflow >/dev/null 2>&1 && echo seeflow |
Every flow mutation goes through the CLI. The studio validates every write server-side — there is no separate validation step. Don't memorise CLI syntax — run $SEEFLOW help to see every subcommand and $SEEFLOW help <command> for synopsis, body shape, output, and error kinds. Treat the help output as the source of truth and follow what it prints. See references/cli.md for the resolver snippet.
Run $SEEFLOW schema BEFORE designing or authoring any node. The CLI is the only source of truth for field shapes, and it's built for cheap progressive disclosure:
$SEEFLOW schema → catalog of categories with subnames inlined on each + a usage block.$SEEFLOW schema <category> (e.g. node, action) → full schemas, notes, subnames, and a jqHints block listing concrete drill paths to try next.$SEEFLOW schema <category> <subname> (e.g. node rectangle, action playAction) → one variant with jqHints.dataFields — the EXACT list of data.<field> names you can target with --jq on the next call.Slice with --jq to pull a single field's contract instead of the whole schema, using a path from jqHints.examples or assembled from jqHints.dataFields:
$SEEFLOW schema node rectangle \
--jq '.schemas.rectangle.properties.data.properties.playAction'
Phase 0 caches the categories; downstream sub-agents are expected to drill into single subnames (with --jq) as they compose patches. Full grammar + every response field in references/schema.md § "Look up the contract at runtime" and references/cli.md § "Schema cache — fetched once at Phase 0".
Any intermediate file the orchestrator or a generated Play/Status script needs (curl output, jq scratch, downloaded fixtures, comparison snapshots, etc.) goes under $SEEFLOW_TMP — never /tmp, /var/tmp, or $TMPDIR. The per-flow path requires no extra permission, survives the run for debugging, and is gitignored by convention (the project lives inside the host's .seeflow/ container, which is gitignored — add flows/*/.tmp/ explicitly if not).
Lifecycle:
mkdir -p "$SEEFLOW_TMP" inside any script or wrapper that writes there. Idempotent, costs nothing."$SEEFLOW_TMP" (or hardcode flows/$flowSlug/.tmp/... relative to $repoPath when running outside a wrapper that exports it).Flow "..." registered ... line, the orchestrator removes $SEEFLOW_TMP (rm -rf "$SEEFLOW_TMP"). On a failed/aborted run, leave it in place — the contents are the debugging trail.flows/*/.tmp/ is not yet gitignored, add it before committing.One message, N Task calls. Narrate each phase boundary with a one-line status (e.g. Phase 3: scaffolding skeleton flow…) so silent waits don't feel broken. The canonical wrong/right block:
Wrong:
message 1: Task(seeflow-code-analyzer, …) → wait
message 2: Task(seeflow-system-analyzer, …)
Right:
message 1: Task(seeflow-code-analyzer, …)
Task(seeflow-system-analyzer, …)
Every later parallel phase (Phase 4 designers, Phase 5 retries spanning both overlay families, Phase 6 per-script fix-up) follows this pattern.
If Agent(subagent_type: "seeflow-…") errors with Agent type '…' not found, the plugin's agent types aren't registered in this environment — fall back to dispatching general-purpose with the matching agents/seeflow-*.md contract inlined into the prompt. Same parallelism rule, same contracts; see references/operations.md §"Sub-agent reference". Never serialise or skip a phase just because the named type is missing.
P0 /health probe ‖ read $learnPath ‖ schema cache (5×)
→ schema-type diff (silent)
→ input-source gate ($inputClass: code | conversation | document)
P1 branches on $inputClass:
code → code-analyzer ‖ system-analyzer
conversation → orchestrator builds brief inline; system-analyzer
runs only if runtime relevant
document → both analyzers skipped; brief built inline
learnUpdates STAGED in memory only — no disk write yet
P2 node-planner (kicks off when brief ready; receives cached
schema + $componentCatalog + $inputClass)
P3 projects:create (path + name → seeflow.json + flows/main/flow.json registered in one shot)
→ flow:add-bulk (nodes + connectors, atomic)
→ detail-backfill (unconditional; missing data.detail → nodes:patch)
→ flows:layout
→ SILENT LEARN.md write #1 (merge staged learnUpdates + upsert flow row)
→ USER REVIEW + dynamic gate (one combined ask)
static branch → SILENT LEARN.md write #2 → final-flow line
P4 play-designer ‖ status-designer (cached schema forwarded)
P5 write scripts to nodes/<nodeId>/scripts/
→ nodes:patch (per node, with playAction / statusAction)
→ optional newTriggerNodes via flow:add-bulk
→ flows:layout
P6 e2e
→ SILENT LEARN.md write #2 (re-upsert flow row + append P5/P6 deltas)
→ final-flow line
Each phase gates on the previous (with the Phase 1 → Phase 2 overlap).
Each phase has its mechanics, contracts, and edge cases in a dedicated reference file. Open the matching file at the phase boundary; the orchestrator does not need to load every phase reference up front.
| Phase | Purpose | Reference |
|---|---|---|
| P0 | Lookup-first gate, capability probe, schema cache, input-source gate, studio probe | references/phases/p0-preflight.md |
| P1 | Discover — three input-class branches (code, conversation, document) and Phase 1→2 overlap | references/phases/p1-discover.md |
| P2 | Plan nodes — launch seeflow-node-planner, validate envelope, retry once on partial output | references/phases/p2-plan-nodes.md |
| P3 | Scaffold via projects:create, normalize, mint canonical ids, flow:add-bulk, detail-backfill, layout, LEARN.md save #1, user review + dynamic gate | references/phases/p3-scaffold.md |
| P4 | Design Play + Status (parallel) — launch seeflow-play-designer ‖ seeflow-status-designer | references/phases/p4-design-overlays.md |
| P5 | Patch overlays + layout — write scripts, nodes:patch, edit-case retype routing, retry budget | references/phases/p5-patch-overlays.md |
| P6 | End-to-end validation — e2e subcommand, fix-up loop, LEARN.md save #2, cleanup | references/phases/p6-validation.md |
Full text in references/core-rules.md:
runtimeProfile.primaryLanguage for every script.flow.json directly. Every mutation is a CLI call.inputClass === "conversation" | "document" — the brief comes from elsewhere.)inputClass === "code"; legitimately skipped for "document".scripts/ / compose / test harness / factory modules) and reuse those wrappers, helpers, and packages. Don't write a raw client when a project module already does the job — the system-analyzer surfaces these in learnUpdates.dataEntryPaths, factories, and techAdaptations.<techId>.helpers[]; Play/Status designers must consult them before inventing new code.flows:create instead of projects:create for a brand-new project. flows:create --project <p> --flow <f> adds a flow to an existing project's manifest; a brand-new project always starts with projects:create, which writes both seeflow.json and the first flows/main/flow.json in one shot.slug as --project. The registry slug is slugify(--name), returned by projects:create — capture it from the response and reassign $projectSlug. The planner's slug field only names the --path directory and may differ; carrying it into --project makes flow:add-bulk / flows:layout fail with projectNotFound.<slug>/scripts/… as scriptPath. The anchor is the node folder under flows/<flowSlug>/nodes/<id>/ — emit just scripts/play.ts.LEARN.md inside a per-project or per-flow folder. $learnPath = $PWD/.seeflow/LEARN.md is shared across every project + flow in the host repo — never inside <projectSlug>/ or <projectSlug>/flows/<flowSlug>/.type:'html' before trying type:'component'. The component catalog is the typed, theme-aware way to render rich node content (status cards, comparison tables, checklists, KPI tiles, gap rows) — and the rule is universal across every inputClass, not just document. html is a last-resort escape hatch, only legitimate once $SEEFLOW schema componentCatalog is confirmed not to cover the content (gap cited in rationales[nodeId]) or when the catalog is unavailable on the installed binary ($hasComponentCatalog === false, i.e. seeflow predates 0.1.94 — see phases/p0-preflight.md). See references/schema.md §"When to use which node type" and agents/seeflow-node-planner.md §"Picking node type".If you catch yourself thinking any of the following, you are rationalising — stop and re-read the relevant rule.
references/core-rules.md. Stop and ask the user.projects:create. The CLI writes the manifest and the first flow envelope atomically; hand-authoring desyncs the two.projects:create returned alreadyExists — I'll quietly run register and continue." → no. Surface the existing-project gate in phases/p3-scaffold.md § 1; auto-fallback is data-loss-adjacent.slug, so I'll use it for --project." → no. The addressing slug is slugify(--name), returned by projects:create. Reassign $projectSlug from the response; the planner's slug only names the --path directory. Mismatch → projectNotFound on flow:add-bulk / flows:layout.Task calls.inputClass === "code". Only "document" flows legitimately skip it.html node — it's only a small comparison table / status card / checklist." → no. type:'component' is the first choice for complex node content (any inputClass); html is only legitimate after $SEEFLOW schema componentCatalog is confirmed not to cover it (gap cited in rationales[nodeId]) or when $hasComponentCatalog === false on the installed binary.$schemaCache.node myself (Python / hand-rolled walker / inline JS)." → no. The "don't memorise CLI syntax — run $SEEFLOW help" rule in §"Conventions" applies to every subcommand, schema included. Run $SEEFLOW help schema once: it documents the <subname> positional for per-variant drill-down AND the --jq <filter> flag for path extraction (jq-subset grammar, badJq exit 2). Reach for those before in-process JSON parsing.--jq got badJq — I'll parse the JSON with Python/JS instead." → no. badJq = wrong path, not a tool failure. Re-run the parent call ($SEEFLOW schema node rectangle) WITHOUT --jq, read jqHints.examples (and jqHints.dataFields for node variants — that's the exact data.<field> list you can target), then retry --jq with one of those paths. Never switch tools.flow:add-bulk for new nodes/connectors, nodes:patch for field edits, nodes:delete for removals, then flows:layout — and don't re-ask a dynamic gate the user already answered. The planner is for turning an open-ended brief into a graph, not for relaying a tweak the user already spelled out. Re-run the planner only for substantive/structural changes. See phases/p3-scaffold.md §"User review + dynamic gate".$SEEFLOW schema runs in milliseconds and tells you exactly which fields each variant accepts; designing before checking burns sub-agent iterations on shapes the CLI would have rejected. Run $SEEFLOW schema <category> (then <subname> for the variant you're about to author) before you draft a single nodes:add / nodes:patch body.| Topic | File |
|---|---|
CLI resolver + discovery via $SEEFLOW help | references/cli.md |
| Error handling, retry caps, sub-agent table | references/operations.md |
| Per-node file convention, action runtime budgets, when-to-use guidance | references/schema.md |
| Core rules | references/core-rules.md |
$learnPath format, lifecycle, merging, learnUpdates contract | references/learn-format.md |
| Tech-specific best practices | references/tech/README.md |
| Sub-agent prompts | agents/seeflow-*.md |
| Canonical id generator | $SEEFLOW ids <node|connector> <count> |