Introduction

><> is a 2D language, meaning programs are executed as a pointer moving around the codespace. The pointer starts in the top left moving right, and each individual character is its own instruction that manipulates either the pointer's direction/position, or the data that is stored on the stack or the actual codespace.

Some more golfing tips can be found at https://codegolf.stackexchange.com/questions/47035/tips-for-golfing-in-fish

Instructions

You can find a list of instructions at https://esolangs.org/wiki/Fish, though it is pretty intuitive once you start getting into it. As a quick reference though (y will refer to the top of the stack, x as second):

Pushing values

><> only has one datatype, rationals, so when you push a string, you are actually pushing a series of codepoints. If you want to push a large number, e.g. 1000, you can use the character at that codepoint ("Ϩ"). Some characters visually affect the code (such as RTL characters), but don't worry, they'll still work (just use a placeholder until then).

Combine strings

With the above tip, you might end up with multiple sets of "" in your code. If you can, try to push all the values at once and then manipulate the stack differently to use them later.

Loops

Single line loop

The pointer is physically moving around the codespace, so you actually have to construct loops physically. The easiest loop is to use the wrapping behaviour of the codespace as a one line loop. For example, io just takes a character of input and outputs it again repeatedly.

If you need to initialise the loop with a value, you can do skip the first instruction on every subsequent loop by appending a ! at the end.

0:nao1+!

Mirror loops

If you want to chain loops together, a good format to use is:

..?\
..?\

Adding on extra lines as necessary. If the first line is longer than the second, try swapping them and shift the mirrors to the start.

/...?
/........?

Jump loops

You can also use . to jump places, most commonly in conjunction with conditions as one coordinate or as both coordinates. You can also use it to skip lengthy initialisation sections.

Use l

This one's very important. A lot of holes require some sort of counter, either as something to filter, and/or to manipulate some persistent value. Instead of starting with 0 and incrementing this every loop, you can instead use the length of the stack and push some arbitrary value each loop. This can be combined with your initialisation process, usually by starting your program with something like 1} or l<. For example, our incrementing program in the loop section can be:

lnao0}

If you find yourself doing changing the value by small amounts afterwards, see if you can move the l to a different spot with the correct stack height e.g. 0l1- => l0$, or l1+nao => alno.

Termination

On code.golf, you can either terminate a program properly with ;, or you can terminate with an error.

Divison/modulo by zero

This can often be used in place of ?;, where you invert the condition and divide the top of the stack by either 1 or 0, e.g. "e"l)?; => "d"l(,. If you already use a division or modulo in your normal code, you may be able to manipulate the divisor/modulus to be zero when you want to terminate.

Invalid instruction

Characters that aren't instructions will throw an error when the pointer hits them. You can use this either by putting a character in the middle of your normal code, directing your pointer into what is meant to be your data section.

Empty stack

There weren't enough elements on the stack to do whatever it was you were attempting. You can use this to terminate by e.g. pushing all the values/input first, then loop assuming the stack is full.

Invalid use of [

The interpreter will error if you try and create a stack with an invalid number of elements (either negative or more than your current stack). This differs from the original interpreter, which only errored on the negative part.

Outputting a negative number

The most common way of doing this is to output the value of EOF (-1).

General tips