Organise your work
Arrange collections, feed requests from environments, and keep your secrets off the repository.
One link that works is a good afternoon. A set of links your team can open, run and review a year from now is a different thing, and it takes three habits: put requests where they can be found, keep the values that change out of them, and keep your own secrets out of the repository. This page covers all three, plus the two ways of finding anything once there is too much to scroll.
Arrange requests in collections
The sidebar is a tree, and it is the same tree as the folders inside
.ryno/collections. Nest it however your project is nested — by feature, by
team, by app — because nothing here expects a particular shape.
Right-click a folder and you get New request, New collection, Rename and
Delete collection. A new collection is created inside the folder you clicked,
so nesting is a matter of where you start rather than a path you type.
Right-click a request and the menu is longer:
Run on devicesends it, exactly like the button in the top bar.Renamechanges the name and the file with it.Duplicategives you a copy to change without losing the original, and is onD .Copy resolved deep-linkputs the finished link on the clipboard, braces filled in.Move to collection…asks where it should go.Delete requestremoves the file, and is on.
Dragging a row onto a folder moves it too, which is usually faster than the dialog for one row and slower for six.
One request, two environments
The point of an environment is that a link you test against staging and a link you test against production are the same request. Copying it is the mistake this whole section exists to spare you: two copies drift, and the one that drifts is always the one you are not looking at.
So write the part that changes as a variable, and leave the rest alone:
https://{{host}}/user/{{userId}}
Then define host and userId once per environment. Switching from one to the
other is
An environment is a name, and behind the name there are two files under
.ryno/environments. For an environment called dev:
| File | Who has it |
|---|---|
dev.env.json |
Everyone. This is the shared half, versioned with the project. |
dev.env.local.json |
You alone. This is the local half, and it never leaves your Mac. |
Both are read, and the local half wins on any name they both define. That is
what lets a shared host sit next to a personal token in the same
environment, and what lets you point one variable somewhere else for an
afternoon without touching what anyone else sees.
You never create either file by hand. The foot of the sidebar names the environment in force and opens the editor for it, where the two halves sit one above the other with their own add buttons: adding a shared value and adding a local one are two different actions, so you cannot put a secret in the versioned half by not paying attention. Creating an environment is done from the same editor, and it exists on disk when you save it, not when you name it.
Write a variable without typing it twice
Type {{ anywhere a value is accepted and Ryno offers the names the selected
environment defines, narrowed as you keep typing. Pick one and the closing
braces are handled for you — including when you are completing inside a pair
you already opened, which is where a second }} would otherwise appear.
Under the URL field, the panel lists the variables this request actually uses, each with the half it came from, and names any it could not resolve. A name no environment defines is not an error and not a guess: it resolves to nothing, and the panel says which one so you find out before the device does.
One thing worth knowing before it bites: a value containing a space is
percent-encoded on its way into the link, because URL-encode values is on.
Turn that option off in the Options tab and the value goes out raw. Neither
is wrong; they test different servers.
Keep a personal token out of the repository
Put it in the local half. That is the whole answer, and the reason it is reliable is that it does not depend on you remembering it.
When Ryno sets up a project it writes a .gitignore inside .ryno, and
*.env.local.json is one of its rules. Opening a project written by an older
version tops that file up rather than replacing it: missing rules are appended,
and any line you added yourself is left where it is. So the exclusion is a
property of the project, not a habit you have to keep.
Two more things follow from it. Local values are masked in the panel under the editor and revealed only when you ask, so a token does not sit in the clear during a screen share. And a value you meant to share but typed into the local half will look right on your machine and be missing on everyone else’s — if a colleague reports an unresolved variable you cannot reproduce, that is the first place to look.
What a colleague gets
Commit .ryno and someone who clones the project gets your collections, your
flows, and the shared half of every environment. Two of the rules Ryno wrote
decide what stays behind: *.env.local.json, which is your local half, and
screenshots/, which is one run on one device on one afternoon.
So the first thing a new colleague has to do is fill in their own local half. Nothing in Ryno can tell them which values they are missing until they run something and read the hole in a resolved link, which makes this the one line worth putting in your own README.
Try something without keeping it
Not every link deserves a file. New scratch, on Scratches section under the tree and writes nothing into your
project.
A scratch is not a request in a folder that happens to be untidy. Four differences, and the third one surprises people:
- It belongs to the app, not to the project. It survives switching
projects, and it is not in
.ryno, so it is never in a review. - It saves itself. There is nothing to confirm and nothing to name; Ryno
calls them
Scratch 1,Scratch 2, and so on. - It has no environment, because environments belong to a project and a
scratch belongs to none. A
{{name}}left in a scratch is not filled in, and Ryno refuses to run it rather than send braces to a device and let you read a failure that means nothing. Replace it with a literal value, or make the request in a collection. - It is not kept forever. Ryno holds on to 20 of them; past that, the ones you have not touched in the longest time drop off by themselves.
When a scratch turns out to be worth keeping, Add to collection… writes it
into the project under a name and a collection you pick, and removes the
scratch once the file is there. Nothing about the request is rewritten on the
way. One thing does change, though, and the dialog says so before you commit to
it: a {{name}} that was inert in a scratch becomes a real variable once the
request is in a collection, resolved by whichever environment is selected when
you run it.
Find anything, two ways
Once the tree is deeper than a screen, scrolling stops being a plan.
Command palette, on New request,
New scratch, New window, Import requests from CSV…, Clone from Git…,
one Switch environment entry per environment, and Toggle theme. Each entry
shows the key that would have done the same thing, so the palette teaches the
shortcuts as you use it.
Search everywhere, on Requests,
Collections, Environments, Devices and Commands at once, and a rail on
the left says how many of each matched. Start the query with one character to
look in one place only:
| Prefix | Looks only at |
|---|---|
> |
Commands, the same list the palette runs. |
@ |
Variables, by name and by value, across every environment. |
# |
Collections. |
/ |
Settings. |
@ is the one to remember. Asking which environment defines a value — or which
one is missing it — is otherwise a matter of opening files, and it is the
question you ask when a link resolves to a hole.
The prefix only counts at the very start, so a # in the middle of a query is
just a character you are searching for.
Keep several requests open
Requests you open become tabs above the editor, and they come back the next time
you open the project. A tab with unsaved changes is marked;
Close the current one with