Skip to content
Ryno

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 device sends it, exactly like the button in the top bar.
  • Rename changes the name and the file with it.
  • Duplicate gives you a copy to change without losing the original, and is on D.
  • Copy resolved deep-link puts the finished link on the clipboard, braces filled in.
  • Move to collection… asks where it should go.
  • Delete request removes 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 E, the picker at the foot of the sidebar, or the command palette, which lists one entry per environment. The request does not change; what it resolves to does.

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 N, gives you a request that lives in the 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 K, is for doing rather than finding: 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 F, is for finding. It looks across 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; S writes the one you are on and S writes all of them.

Close the current one with W. Move along the row with and , or jump between the two you have used most recently with , which is the one that pays off when you are comparing two links.