Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Flow

ASecurity

How to use @owlmeans/flow — a serializable step/transition state machine whose whole state collapses to one string. Auto-invoked when importing from this package, driving a multi-step workflow, or restoring one from a token.

3 stars
0 votes
0 copies
0 views
Added 9/22/2026
devopstypescriptgo

Works with

cli

Security Analysis

A100/100

Scanned 9/22/2026

Install to Claude Code

$npx -y skills add owlmeans/common --skill flow --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Flow?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Flow
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/owlmeans-flow-common/badge)](https://www.skillsdirectory.com/skills/owlmeans-flow-common)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: flow
description: How to use @owlmeans/flow — a serializable step/transition state machine whose whole state collapses to one string. Auto-invoked when importing from this package, driving a multi-step workflow, or restoring one from a token.
user-invocable: false
---
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->

# @owlmeans/flow

**Layer:** Cross-cutting domain
**Install:** `"@owlmeans/flow": "^0.1.18-rc.31"` in `dependencies`

A flow is a set of named **steps**, each offering named **transitions** to other steps. What makes
it worth using over a hand-rolled switch is that the whole live state — `flow`, `step`, `previous`,
`service`, `entityId`, `payload`, `message`, `ok` — serializes to a single compact string and
restores from it. That is what lets a workflow survive a redirect, a page load, or a process.

## Key exports

| Export | Description |
|---|---|
| `makeFlowModel(flow, provider?)` | Build a driver. `flow` is a `ShallowFlow` **object** (no provider needed) or a **string** — tried as a flow name first, then as a serialized token. |
| `FlowModel` | `target` `entity` `enter` `steps` `state` `setState` `payload` `updatePayload` `step` `transitions` `transition` `next` `transit` `serialize` |
| `ShallowFlow` / `FlowStep` / `FlowTransition` / `FlowState` / `FlowPayload` / `SerializedFlow` | The definition, the live state, and the compact shape the token encodes |
| `Flow` | A `ShallowFlow` a provider resolved: it also carries the resolved `config` and the `prefabs` — one serialized entry state per initial step |
| `FlowProvider` | `(flow: string) => Promise<Flow>` — resolves a flow by name |
| `FlowConfig` / `WithFlowConfig` / `FlowConfigRecord` | `{ queryParam, services, modules, pathes, defaultFlow }`, the `flowConfig` field it sits on, and the config-record form of a definition |
| `flow(cfg, flow)` · `configureFlows(cfg, config)` | Register a definition as a `FLOW_RECORD` config record / set `FlowConfig` |
| `stdStabFlow`, `stdOidcFlow`, `stdOidpFlow`, `stdAuthFlow` (deprecated) | Built-in flows, with `StdAuthStep` / `OidcAuthStep` / `OidpAuthStep` naming their steps |
| `STD_STAB_FLOW` `STD_OIDC_FLOW` `STD_OIDP_FLOW` `STD_AUTH_FLOW` | Their names — deliberately short, because every one of them is spent inside a URL |
| `FLOW_RECORD` (`flow`) · `CFG_FLOW_PREFIX` (`flow`) · `TARGET_SERVICE` (`-`) · `FLOW_PLACEHOLDER` (`?`) · `FLOW_SEP` · `PAYLOAD_SEP` | Constants |
| `FlowError`, `FlowUnsupported`, `FlowTargetError`, `UnknownFlow`, `FlowStepError`, `FlowStepMissconfigured`, `UnknownFlowStep`, `UnknownTransition` | The error family, all registered with `ResilientError` |

## Defining a flow

A definition is data, not a class. Each step carries an `index`, its own `step` name, the `service`
it belongs to, and a map of transitions keyed by transition name:

```typescript
import type { ShallowFlow } from '@owlmeans/flow'

export const onboardingFlow: ShallowFlow = {
  flow: 'onboarding',
  initialStep: 'welcome',
  steps: {
    welcome: {
      index: 0,
      step: 'welcome',
      service: 'onboarding',
      initial: true,
      transitions: {
        next: { transition: 'next', step: 'profile' },
      },
    },
    profile: {
      index: 1,
      step: 'profile',
      service: 'onboarding',
      transitions: {
        next: { transition: 'next', step: 'done' },
        back: { transition: 'back', step: 'welcome', explicit: true, reversible: true },
      },
    },
    done: { index: 2, step: 'done', service: 'onboarding', transitions: {} },
  },
}
```

## Driving it

```typescript
const model = await makeFlowModel(onboardingFlow)   // an object needs no provider
model.transit('next', true)                          // → 'profile'
const token = model.transit('next', true)            // → 'done'; returns the SERIALIZED state

const restored = await makeFlowModel(token, provider)   // a token DOES need a provider
restored.step().step   // 'done'
```

## Rules

**`transit()` returns the serialized state, not the model.** It is the natural place to persist or
hand off from — a caller that ignores the return and calls `serialize()` afterwards gets the same
string, but the return is the signal that a transition is a checkpoint.

**A string argument is a flow name FIRST and a token second.** `makeFlowModel` asks the provider,
and only re-reads the string as a serialized token once the provider **throws**. A provider that
returns `null`/`undefined` for an unknown name therefore breaks every restore — it must throw
(`UnknownFlow` is what the built-ins raise).

**Passing a `ShallowFlow` object needs no provider at all.** That is the server-friendly path: a
runtime whose flows are code it declares itself needs no registry to start one, only to restore one.

**`next()` answers with the first non-explicit outgoing transition**, and throws
`UnknownFlowStep('next')` when the step offers none. It is what lets a driver advance without
knowing the vocabulary, so mark every user-chosen or exceptional edge `explicit` — an unmarked
second edge silently becomes reachable as the automatic answer.

**`enter(step?)` only accepts a step marked `initial`**, and throws `FlowStepError('initial:<step>')`
otherwise. That is what makes a flow's entry points an explicit part of its definition rather than
whatever the caller happens to name.

**`FlowPayload` holds flat scalars only** — `string | number | boolean | null | undefined`. Anything
richer belongs in a record the payload points at. Payload is projected through the step's
`payloadMap` on serialization, so an unmapped key does not survive a round trip and a step with no
`payloadMap` at all carries no payload across.

**`updatePayload` merges; `transit` also merges.** Neither replaces the payload, so a key set early
in a flow keeps arriving at every later step whose `payloadMap` names it.

**The live state is `flow` `step` `previous` `entityId` `service` `payload` `message` `ok`.**
`service` is the target the flow is running *for*, set through `target()`; `entityId` is set through
`entity()` and survives serialization even when it is explicitly `null`.

**`reversible` is what keeps `previous`**, and is what a "back" transition needs to return to where
it came from.

## Where it runs

Client drivers are `@owlmeans/client-flow` (`makeBasicFlowService`) and `@owlmeans/web-flow`
(`makeFlowService`, which supplies the browser redirect the basic service refuses); they load
definitions from `FLOW_RECORD` config records through the config resource and carry the serialized
state in a query parameter (`FlowConfig.queryParam`, defaulting to `flow`).

A step addresses its screen through `module` — the alias of the entrypoint the driver navigates to,
which is why a step is portable between apps that mount it at different paths. `service`, `module`
and `path` are plain strings, and a value prefixed with `$` is a reference resolved at load time
against `FlowConfig.services` / `modules` / `pathes` — which is how one definition is reused by
deployments that address different services. `TARGET_SERVICE` (`-`) in a step's `service` means
"whatever the state's own target is" rather than a named one.

A step with no `module` cannot be addressed, and the two client drivers raise
`FlowStepMissconfigured` at different moments: `FlowClient.proceed` in `@owlmeans/client-flow`
checks the step it is about to **enter**, before it transits; `FlowService.proceed` in
`@owlmeans/web-flow` checks the step the model is **standing on**. Either way the step named in the
error is the one missing the `module`.

There is **no server-side driver in this package**. A server or worker builds models directly from
`ShallowFlow` objects and supplies its own `FlowProvider` for restores — `@owlmeans/agent`'s
`makeStaticFlowProvider` is the reference implementation of one.

## Depends on

`@owlmeans/auth`, `@owlmeans/config`, `@owlmeans/error`, `@owlmeans/i18n`, `@owlmeans/resource`,
`@scure/base` (the token codec — base64url, no padding, over the JSON of `SerializedFlow`).

## Related

- [[client-flow]] — the client service and the runner a screen drives
- [[web-flow]] — the browser half: the `flow` query parameter and cross-service redirects

Attribution

owlmeansowlmeans
View sourceMore from owlmeans →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Terraform Module Library

Build reusable Terraform modules for AWS, Azure, and GCP infrastructure following infrastructure-as-code best practices. Use when creating infrastructure modules, standardizing cloud provisioning, or implementing reusable IaC components.

397921 votes

sematext-otel

Wire a service's OpenTelemetry output to Sematext Cloud. Walks through region, App-type, instrumentation flow (managed OTLP endpoint vs Sematext Agent), and signal selection (traces/metrics/logs), then produces the exact env-var block and points at a runnable reference example in this repo. Invoke when instrumenting a new app for Sematext.

01 votes

Deployment Patterns

Deployment workflows, CI/CD pipeline patterns, Docker containerization, health checks, rollback strategies, and production readiness checklists for web applications. Use when setting up deployment infrastructure or planning releases.

2459130 votes

Babysit

Watch a pull request or review cycle until it is ready to merge. Use when asked to babysit, monitor, or keep checking PR comments, reviews, and CI until all actionable issues are resolved.

942310 votes

V7 Roster

Interact with the Paperclip control plane API for task coordination and governance. Use when checking assignments, updating issue status, posting comments, delegating work, managing routines, or calling Paperclip API endpoints.

805540 votes
View all in devops →