agent.md

September 11, 2026 · View on GitHub

Culebra

Source files are .cul. There is no manifest and no package manager; the whole standard library is in scope without an import.

culebra prog.cul          # run (the bytecode VM's executor)
culebra --jit prog.cul    # the same output, that bytecode lowered to LLVM
culebra test              # run every test_*.cul below the cwd
culebra fmt -i .          # format in place (no style options)
culebra lint .            # static checks

Look an API up instead of guessing it — especially the ones that feel too ordinary to check. sort, take, items, length: a name every language has is where a wrong guess is most confident and least noticed. The whole reference is inside the binary, so it always matches the build being run:

culebra docs -g 'Math.wrap'          # print the sections that match
culebra docs -g '<name>' >/dev/null  # exits 1 when nothing matches
culebra docs stdlib Scene            # print one namespace's chapter whole

Exit status is grep's: 0 printed something, 1 nothing matched. A signature -g cannot find does not exist.

Read culebra docs quick-guide before writing Culebra. It is one prompt-sized file: the syntax, the signatures a program reaches for unprompted, and a table of the habits from other languages that do not carry over. One row of that table, for the kind of thing it covers:

# !! TypeError
'ab' * 3

The quick guide names the stateful subsystems — Scene, Canvas, Net, PEG, CodeGen and the rest — rather than listing them. Print the chapter for one before writing against it; its signatures alone do not say in what order to call them or what owns the result.

Run what you write. Undefined names are rejected before the program starts, but that check covers names, not members: Math.abss(1) and xs.len() survive culebra lint and fail when the line runs, and a missing property is nil rather than an error.