drawing-step-flows
Skill2 starsChanged 2 months agoMITView on GitHub
Use when drawing a numbered step flow — how a request, a user or a token moves through an app and its services, step 1, 2, 3 — as a .drawio / draw.io file. Also called an app flow, call flow, auth flow, integration flow, solution flow or sequence-of-steps diagram, and for fixing one whose steps are unnumbered or whose connectors cross boxes
In this repository5 other files it gives its agents.
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 27
Use the folder the user names.
- Very specific: line 34
Never leave a build script, a .drawio or a preview in the project root, and never write outside the project you were pointed at.
- Distinctive: line 105
Every connector leaves and arrives straight — 26px along the normal of the face it uses, before it turns.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Drawing step flows
A .drawio step flow in the same visual language as the architecture diagrams
and the flowcharts: light page, white cards with hairline borders, Google's
palette on the connectors, and a numbered blue disc on every step.
Build it with step_drawio.py (this directory). Check it with
check_routing.py. Look at it with preview.py.
Where the files go
Everything this skill produces lives in one folder, never loose in the project root:
docs/diagrams/
upload-flow.py # the script that builds it
upload-flow.drawio # the diagram
upload-flow.preview.svg # what you looked atUse the folder the user names. Otherwise put it under docs/diagrams/ when the
project has a docs/ directory, and diagrams/ at the project root when it
does not — the build script, the .drawio, and any preview or PNG together.
write() creates the folder if it is missing, so
f.write("docs/diagrams/upload-flow.drawio") is all it takes, and preview.py
writes the SVG beside its input.
Never leave a build script, a .drawio or a preview in the project root, and
never write outside the project you were pointed at. One folder, named files —
a diagram whose script sits next to it can be regenerated; one scattered across
a repository root cannot be found again.
What this draws, and what it does not
| step flow (this skill) | what happens, in what order, between which parts — 1, 2, 3 |
| architecture diagram | what the system is made of: zones, panels, what talks to what |
| flowchart | what is decided: questions with two answers, branches, loops |
The test is whether the numbers mean anything. If the arrows have no order — if it is a picture of a system rather than of a sequence — draw it with the architecture skill. If the path forks on a question, that is a flowchart.
The output contract
- Every connector routed.
direct=,bend=,corridor=orpoints=. There is no default. check_routing.pyreporting 0 FAIL.- The numbers read 1..n with no gaps.
step()numbers for you, in call order, so write the calls in the order the thing happens. - Anything that is not a step is a
link()— dashed, grey, unnumbered.
The pieces
from step_drawio import Steps, L, R, T, B
s = Steps("Power BI reads BigQuery", "workforce identity federation")
bi = s.node("Power BI", "report author",
icon="onprem/analytics/powerbi.png", col=0, row=0)
entra = s.node("Azure AD / Entra ID", "identity + groups + token issuer",
icon="azure/identity/azure-active-directory.png", col=1, row=0)
wif = s.node("GCP Workforce Identity Federation", "Workforce pool + provider",
icon="gcp/security/iam.png", col=0.5, row=1)
s.step(bi, entra, exit=R(), entry=L(), direct=True)
s.step(entra, wif, "OIDC token + groups", exit=B(), entry=R(), bend="VH")
s.write("docs/diagrams/flow.drawio")node() is a card: a bold title, a grey subtitle saying what it is here for,
and an optional icon. note() is commentary — not a step, never numbered.
A column may be fractional. col=0.5 puts a node between the two above it,
which is usually where the thing that sits between two systems belongs.
Routes
direct=True | a straight line between two nodes in the same row or column, with nothing between them — checked, not assumed |
bend="HV" | across, then down: one corner, at the target's x |
bend="VH" | down, then across: one corner, at the source's y |
corridor=s.corridor(after_col=N) | a vertical lane in the gutter, for a step that leaves and arrives through a side and has to pass other nodes |
band=s.band(below_row=N) | a horizontal lane under a row — the return path, out of a bottom and into another bottom |
points=[...] | a route no single corner, corridor or band can express |
Most steps in a step flow are direct or a bend. Reach for a corridor when
the step has to travel past something, and for points= only when neither
fits.
Which lane you want follows from the faces: out of a side and into a side is a corridor, out of the top or bottom and into one is a band. Ask for the other one and it is refused, because that route turns two corners more than it needs and the picture shows it.
Every connector leaves and arrives straight — 26px along the normal of the face
it uses, before it turns. That is what keeps an arrowhead pointing into the
card rather than skidding along its edge, which reads as a bend right at the
tip. A direct step between two faces that are not quite level puts its step
halfway along, not next to the arrowhead.
exit= and entry= are always required — L() R() T() B(), optionally with a
fraction, R(0.3). Two connectors leaving the same face are spread apart
automatically, so they do not lie on top of each other on the way out.
The number is the point
step() takes the next number. link() takes none: a feed, a fallback, a
side effect that happens whenever, not at step 4. Keeping those unnumbered is
what makes the numbers worth reading.
The disc rides its connector. Where exactly is worked out at write time, with
every route known: clear of other lines, of crossings, of cards, and of the
other discs, as near the middle as those allow. The label gets its own spot on
the same terms. Pass at= (-1 at the source, 1 at the target) to overrule the
choice for one disc; it is then left alone.
Both positions are written into the file, so draw.io and the preview show the same picture — a preview that quietly moves what the file pins is worse than one that draws it badly.
Icons
The diagrams package's icons, by path or by name:
python3 ~/.claude/skills/drawing-step-flows/step_drawio.py bigqueryPass what it prints: icon="gcp/analytics/bigquery.png". A card with no icon
is fine — the label simply starts at the left edge.
Geometry
| node | 260 wide, 66 tall, taller when its label needs it |
| column pitch | 420 (node 260, gutter 160, 4 corridors) |
| approach | 26 straight out of a face and straight into one |
| lane inset | 46, so a lane clears the approach line rather than shadowing it |
| row pitch | 175 |
| disc | 22 |
The page measures itself from what is on it. width=/height= are a floor.
Before handing it over
S=~/.claude/skills/drawing-step-flows
python3 "$S/check_routing.py" docs/diagrams/flow.drawio # must report 0 FAIL
python3 "$S/preview.py" docs/diagrams/flow.drawio # writes docs/diagrams/flow.preview.svg
rsvg-convert -w 1400 -o docs/diagrams/flow.png docs/diagrams/flow.preview.svgThen read the picture for what a checker cannot see: a step whose label repeats its target's title, two steps that are really one, a number sequence that no longer matches the prose it illustrates.
Common mistakes
| Unnumbered arrows | Then it is not a step flow. Number them, or draw it as an architecture diagram. |
| Everything numbered | A feed that runs nightly is not step 5. Use link(). |
| Steps written out of order | step() numbers in call order. Write the calls in the order it happens. |
| A label repeating the target | "sends to BigQuery" on the arrow into BigQuery says nothing. Say what travels: "OIDC token + groups". |
| A fork in the path | Two arrows out of one node with no question is a lie. That is a flowchart. |
| An arrowhead that bends into the card | The last hop is running along the face. Both lanes and both bends already end straight — a hand-written points= has to do it too. |
| Reporting done without the checker | The routing failure is invisible until it renders. |
preview.py writes a plain SVG — open it in any browser if you have no rsvg-convert. The PNG step is for pasting into a document, not for looking at it.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

