Run a flow
Chain requests into a scenario, answer as you go, and read the report it leaves behind.
One link answers one question. Signing off a release does not: someone has to walk a dozen links in order, decide after each one whether the app did the right thing, and leave behind something a developer can act on the next morning. That is what a flow is for, and this page follows one from an empty file to a report you can reopen a week later.
Switch to flows
Flows are the second of the three modes in the rail down the left of the window.
Pick it there, or press
New flow in the sidebar header asks for a name and writes one file under
.ryno/flows, next to your collections and versioned with them. The sidebar
then lists every flow with how its last run went, or not run yet for one
nobody has launched.
Under the title sits a description. Write what the scenario is meant to verify: it is stored in the flow file, so it is the first thing a colleague reads when they inherit the flow six months from now.
Add the steps
Three buttons, three ways in:
Add request…picks one request out of your collections.Add collection…pulls in a whole folder at once, in its own order.Custom stepwrites a link straight into the flow, with no request behind it. Useful for the one-off nobody wants to keep.
The order of the list is the run order — nothing else ranks steps. Drag a
card to move it, or use Move up and Move down in the step’s menu, which also
holds Delete step. Those two exist so that reordering never requires a
pointer.
A step points at a request, it never copies it
This is the rule the rest of the page rests on. A step added from your collections holds the path of that request, not a copy of it.
Two things follow, and both are the reason flows are worth keeping:
- A request you fix is fixed everywhere. Correct a typo in the link once and every flow that uses it launches the corrected one. Nothing goes stale behind your back, which is what would otherwise turn a healthy flow into a fake regression.
- A flow never writes back. Nothing you do inside the flow reaches the
request file under
collections. You can retune a whole scenario without touching what anyone else runs.
Rename the request and the step follows it, because a step with no label of its own shows the request’s name.
Delete the request and the flow still runs. The step is recorded as skipped,
with the reason, and the recap still accounts for it — a run that quietly
dropped half a scenario would read as a clean pass. The step’s menu then offers
Relink…, to point it at another request, and Convert to inline, to keep the
link it last knew as its own.
Override a value for this flow only
Expand a step and you get every value it can substitute, with the source’s value
beside it. Type over one and only this flow sees it; the panel says so above the
table. Reset to source drops the whole layer at once, and dropping the last
value returns the step to exactly the state it had before you overrode anything.
Run options behave the same way, with the same controls as the request editor’s
Options tab, because they are the same options. A step inherits every option
from its source and stores only the ones this flow decides, so each row can say
whether it is following the request or the flow — and one gesture puts it back
to inherited.
That is what lets one request serve two scenarios: the same link, with a
different identifier in the path here and Force-stop app first on there,
without a second copy of anything.
Decide when screenshots are taken
An image per step is what turns a report into something a developer can read without you in the room. Where you decide it is the part worth knowing: the choice belongs to the flow, not to each step, and it sits in the brief next to the description.
| Setting | What it captures |
|---|---|
Per request |
Whatever each step’s own screenshot option asks for. This is the default. |
Never |
Nothing at all, whatever the steps ask for. |
Every step |
One image per step the run launches, passed and failed alike. |
On failure only |
Only the steps you answer as failed. |
On success only |
Only the steps you answer as passed. |
Two things about this surprise people, and both cost a session when they bite.
A screenshot on a verdict is taken when you answer, not when the step
launches. Under On failure only and On success only the image is grabbed
at the moment you press the answer, so what it holds is the screen you were
looking at while judging — not whatever the app had drifted to a second after
the link went out. Per request is the exception, and the older behaviour: it
captures once the launch settles.
The setting is shared, the images are not. Your choice is written into the
flow file, so it travels to your team through the project like everything else
in .ryno. The images do not: they land in .ryno/screenshots, which Ryno
excludes from the repository with a screenshots/ rule the moment it sets a
project up. So a colleague who pulls your flow inherits the policy and none of
the pictures, which is what you want — one run, on one device, on one afternoon.
One device cannot be captured at all: a cabled iPhone, whose tooling has no screenshot verb. Pick a policy that promises an image on that fleet and the app says so under the picker rather than letting you find out from an empty report.
Start the run
Run flow sits at the top of the flow, in the same green as the run button in
the top bar, and it wants two things: a device selected and at least one step. A
step whose request has gone missing is not one of them — it is skipped by the
run, never a reason to hold the whole scenario back.
The runner then takes the entire window. That is the feature, not a flourish: during a run your eyes are on the phone, and the screen has to answer which step, which link, which device in one glance from across a desk. Everything else in the app is out of reach until you are done, so nothing can be clicked by accident with a phone in your other hand.
Answer each step with one key
Each step launches, and then the runner asks you one question. Answer it with
No modifier, on purpose. During a run one hand is holding a device, so an answer has to cost one key. Two consequences come with that, and the second one is the one to remember:
- These three keys only mean anything while a run is up. Outside the runner they belong to whatever has focus, exactly like any other letter.
- They go quiet while you are typing into a field. Without that rule the form on the next screen would be unusable, since the words you write about a failure are full of the letters those keys are bound to.
So the short version, if you only keep one line: press the key when the question is on screen, use the buttons when the cursor is in a text box.
Say what went wrong
Answering that a step did not work unfolds a short form with two questions — what happened, and what you expected instead. The gap between the two answers is the bug description, and it is what somebody who was not there will read.
Neither field is required. A tester who saw the failure and cannot phrase it
must still be able to move on: a run recorded as failed and undescribed is worth
more than a run stalled, and far more than a Yes pressed to get past a form.
Back returns you to the question if you answered by mistake.
When the launch itself fails
Sometimes nothing reaches the app at all — the device went away, the simulator shut down, the tool refused. The runner treats that as its own outcome and says so in as many words: it is a technical error, not a failed check, and the step was never verified. Reading it as a product bug is how a tooling problem turns into a bug report nobody can reproduce.
You get the exit code, the exact command that was sent, and the tool’s own
output. Retry step runs the same step again once you have plugged the cable
back in; Continue run carries on to the next one. Neither ends the run for
you, and the failure is already recorded either way.
A cabled iPhone is the fleet where this matters most, for the reason a single link already showed you: Ryno hands the link to the app you named and gets a clean answer back whether or not the app understood it. Inside a flow that has a plain consequence — the launch confirms nothing, so your own answer is the entire verdict, and no screenshot can be taken to back it up. Everything the report holds for that step came from you.
Read the recap
The run ends on a summary: the three totals, then every step with its verdict, in flow order and skipped ones included.
Each line carries what a reader needs and nothing else — the reason for a skip, the words you typed about a failure, and one sentence saying whether a screenshot was taken and, when it was not, why. Those reasons are not interchangeable, so they are spelled out separately: the flow’s policy excluded this step, the step’s own option was off, the device cannot be captured, the capture failed, or the step never launched at all.
Back to editor closes the runner. The report is already saved by then.
Find the report again
Reports mode, on
A report is self-contained. It stores the flow’s name, the device and the family it belongs to, the links that were launched and the step labels as they were at run time, so renaming the flow, reordering it or deleting it outright never changes what an old report says. That is the whole point of keeping one.
Two actions sit in its header. Copy prompt for AI puts the failures on the
clipboard already written up as something you can paste into an agent, which is
usually faster than describing them again. Delete run removes that one record.
One limit worth knowing before you lean on it: this history is personal to your machine and stays out of the project, and it is bounded. Ryno keeps around 50 MB of run history per project — tens of thousands of runs — and once past that the oldest ones drop off on their own. It is a trail, not an archive: a report you need to keep is one you should copy out.