flow-basics
Skill1 starsChanged 3 months agoMITView on GitHub
Write, compile, and run an ordinary Flow program. Use for any general Flow coding task, for the syntax of variables, functions, structs, arrays, control flow, imports, and C interop, and whenever you need to check that a Flow file actually runs.
In this repository13 other files it gives its agents.
- AGENTS.mdAGENTS.md
- flow-audioSkill
- flow-autodiffSkill
- flow-compiler-devSkill
- flow-debugSkill
- flow-dynamicsSkill
- flow-effectsSkill
- flow-graphicsSkill
- flow-perfSkill
- flow-setupSkill
- flow-stdlibSkill
- flow-verifySkill
- flow-wasmSkill
The file
We split this skill into the rules it gives an agent
1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 168
Do not invent syntax from another language.
≈ “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
Writing ordinary Flow
Most Flow work is ordinary code. Reach for a declarative form when it improves the model, not to save a line.
Choose the route before writing
| Decision | Choices | Default |
| Compiler host | flowc, python | python unless the program is pure Stage-A |
| CPU backend | C, MLIR | C |
| Mode | run, compile, gfx, audio, wasm | The one closest to the real target |
Anything with println, a flow block, an effect, or generics needs
FLOW_HOST=python.
The syntax
# Comments start with a hash. There are no line comments with slashes.
let x: i32 = 42 # immutable
let mut count: i32 = 0 # mutable
count = count + 1
const GRAVITY: f64 = 9.81 # file-level constant
function add(a: i32, b: i32) -> i32 {
return a + b
}
function greet(name: string) -> void {
println(name)
}
struct Point {
x: f64,
y: f64
}
function main() -> i32 {
let p: Point = Point { x: 1.0, y: 2.0 }
println(p.x)
let values: array<f64, 4> = [1.0, 2.0, 3.0, 4.0]
println(values[2])
for i in 0 to 10 { # 0 up to but not including 10
if i % 2 == 0 {
println(i)
}
}
let mut n: i32 = 5
while n > 0 {
n = n - 1
}
if n > 0 {
println("positive")
} elif n < 0 {
println("negative")
} else {
println("zero")
}
return 0
}Scalars are i32, i64, f32, f64, bool, string, void. Low-level
work uses ptr<T>. Casts use as, for example count as f64.
Signatures always carry explicit types. main returns i32, where zero means
success and any other value is a failure code you choose.
Printing
println("text")
println(some_number)
extern {
function printf(fmt: string, val: f64) -> i32
}
printf("%.4f m\n", height)println takes one value. For formatted output, declare printf in an
extern block, which is what the shipped examples do.
Imports
import "stdlib/text.flow"
import "stdlib/math.flow"
import "stdlib/dynamics/state_space.flow"Library imports are quoted paths rooted at stdlib/, which resolves to
lib/stdlib/ in the checkout. Look in lib/stdlib/ for what exists before
writing a helper. The flow-stdlib skill covers searching.
C interop
extern {
function sqrt(x: f64) -> f64
function fabs(x: f64) -> f64
function malloc(size: i64) -> ptr<void>
}Declare only the surface you need. A parser-accepted extern is not proof that
the symbol links. Compile and run before claiming it works.
Run it
FLOW_HOST=python flow run program.flow # compile and run
FLOW_HOST=python flow compile program.flow # compile only
flow fmt program.flow # format
flow explain program.flow # show the compilation planOr use the packaged wrapper, which tries the fast host, falls back to the full one, and prints the command that worked:
flow-check program.flowGenerated C lands in $FLOW_HOME/build/. Reading it is a good way to
understand what a construct lowered to. Never edit it; it is regenerated on
every build.
Verify before reporting
A program that compiles has not been shown to be correct. Make main check
something and return a distinct code per failure:
function main() -> i32 {
if add(2, 2) != 4 {
return 1
}
if sum_to(10) != 55 {
return 2
}
println("OK")
return 0
}Then report the exact command, the real output, and the exit code.
Pitfalls
- Comments use
#. Slashes are not comments. - Ranges are
0 to n, exclusive ofn. There is no..form. letwithoutmutcannot be reassigned.- The default host silently lacks
println; the error names the Stage-A subset. - Do not invent syntax from another language. Grep
examples/for a construct before using 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.

