// Documentation
The whole language
in one page.
GeoScript is intentionally small. One syntax pattern, a handful of concepts, then the in-app search and AI do the rest. This page is a quick orientation — not an exhaustive reference.
One pattern, every object.
Every GeoScript statement has the same shape. Once you've written three lines, you know the syntax for everything.
type Name: (arg1, arg2, arg3, …)
The type says what kind of thing you're creating. The name lets you reference it later. The arguments describe it. That's it.
// Every line follows the same pattern axes A: ((-6, 6), (-5, 5)) grid G: (A, 1) point O: (0, 0, teal, 4) circle C: (O, 3, teal, 1.5, teal.alpha(0.06)) pointOn P: (C, 45, amber, 5) segment s: (O, P, amber, 1) label lP: (P, "P", amber, 11)
Two ways to pass arguments.
Arguments can be positional (in order) or named (by key). You can't mix them in a single statement — pick one style and use it consistently.
circle C: (O, 3, color=teal)
circle C: (O, 3, teal)
circle C: (center=O, 3, teal)
circle C: (center=O, radius=3, color=teal)
Optional arguments with defaults can be dropped from the right. So circle C: (O, 3) is perfectly valid — it just inherits the auto-colour and default stroke width.
zIndex= can always be appended as a named arg regardless of whether the rest are positional — segment s: (A, B, teal, 1.5, zIndex=2).Points everywhere.
Any argument that expects a point accepts two forms interchangeably.
named A defined point object
point A: (0, 0, white, 4) segment s: (A, B, teal) // A and B are point objects
inline A literal coordinate pair
segment s: ((0, 0), (4, 3), teal) // inline pairs, no point objects needed
math Expressions work in coordinates
segment s: ((0, 0), (pi/2, sin(pi/2)), orange) point P: (pi, F(pi), white, 5) // F is a defined fn object
The dot-access system (see below) means you can also derive points from existing objects — s1.mid, cc.center, T.centroid.
Colour without friction.
GeoScript has a built-in palette of named colours — type them directly as arguments. You can also define your own palette with col and reuse it with alpha variants.
// Built-in names — just use them circle C: (O, 3, teal, 2) // Name.method for transparency circle C: (O, 3, teal, 2, teal.alpha(0.08)) // Hex colour circle C: (O, 3, #4fd1c5, 2) // Custom palette — define once, use everywhere col brand: (#2563eb) circle C: (O, 3, brand, 2, brand.alpha(0.1))
Named colours: teal · mint · amber · violet · rose · orange · indigo · sky · emerald · lime · cyan · red · blue · green · yellow · pink · purple · white · grey
Colour methods: .alpha(0–1) for transparency, .lighter and .darker for tints.
If you omit a colour entirely, GeoScript auto-assigns from a rotating palette — useful for quick sketches where aesthetics don't matter yet.
The dot system.
Every referenceable object exposes computed properties via dot access. This is how GeoScript constructions compose — the output of one object becomes the input to the next.
segment s: (A, B, white, 1.5) // Use the midpoint as a label anchor label lm: (s.mid, "midpoint", teal, 10) // Use derived coordinates directly point M: (s.mid.x, s.mid.y, teal, 4) // Chain: midpoint of the segment's midpoint to another point midpoint MM: (s.mid, C, violet, 4)
A few common examples across different types:
| Expression | What it gives you |
|---|---|
| segment.mid | Midpoint as a point object — usable anywhere a point is expected |
| segment.length | Euclidean length as a number |
| circle.center | Centre point |
| circle.radius | Radius as a number |
| triangle.centroid | Centroid point |
| circumcircle.center | Circumcenter of the triangle |
| integral.value | Computed definite integral as a number |
| crossing.x / .y | Coordinates of the intersection point |
| diff.slope | Derivative value at the given x |
| tangentTo.t1 / .t2 | The two tangent points on the circle |
Math inline.
Arithmetic works anywhere a number is expected. Defined fn objects are callable by name.
// Arithmetic — all four operators plus power point P: (2*pi, 3^2 - 1, white) // Math functions and constants point Q: (pi/4, sin(pi/4), amber, 5) // fn objects are callable fn F: (x^2 - 2*x, violet, 2) point R: (3, F(3), rose, 5) // These all work as integral bounds integral I: (F, 0, 2*pi, true, teal.alpha(0.25))
Available functions: sin cos tan asin acos atan sqrt abs exp ln log2 pow min max floor ceil round
Constants: pi tau inf
Operators: + − * / ^ (power is right-associative: 2^3^2 = 2^(3^2))
Comments & style.
// Full-line comment — anything after // is ignored point O: (0, 0, white, 3) // inline comment works too
Names must be unique across the whole diagram. Beyond that, GeoScript doesn't enforce naming conventions — use single letters for brevity, descriptive names for clarity, whichever serves the diagram.
Blank lines are fine and encouraged — group related statements visually, separate setup from construction from annotation.
The search is the reference.
GeoScript's in-app search is the authoritative type reference. Every type in the language is listed there with its full schema, an insertable example, and all dot-access properties.
Press ⌘K in the app
Search any type name, keyword, or concept — "circle", "midpoint", "integral", "inscribed". Open a result for the full schema, a copy-paste example, and every dot-access property listed with descriptions.
The search is generated directly from the type registry — the same source of truth as the language itself. It's always current, always complete, and always correct. This documentation page intentionally doesn't list every type argument — the search does that better.
↑ insert in any search result to drop the example snippet directly into your editor at the cursor position. Useful for types you use rarely and don't have memorised.The number scrubber.
Select any bare number in the editor and a slider appears at the bottom of the code panel. Drag it and the canvas updates in real time — no retyping, no re-running. Every frame is a live render.
point Q: (1+h, sin(1+h), violet, 5)
The slider range is inferred from the value's magnitude — a small number gets a tight range, a large one gets more headroom. Press Escape or click elsewhere to dismiss.
SHIFT Fine control
Hold Shift while dragging to switch to fine mode — step drops to 0.01 and precision increases to two decimal places. A FINE badge appears on the slider bar while the key is held. Release to return to normal step.
point Q: (1+h, sin(1+h), violet, 5)
num Parametric diagrams
A single scrubbed number only updates the one literal you selected. To make a value flow through an entire construction — animating multiple objects at once — declare it as a num variable and reference it by name everywhere it's needed.
// Scrub h toward 0 — watch the chord rotate to meet the tangent axes A: ((-1, 3), (-1, 2)) grid G: (A, 1) ticks T: (A, 1) num h: (1.0) fn F: (sin(x), teal, 2) point P: (1, sin(1), orange, 5) point Q: (1+h, sin(1+h), violet, 5) segment chord: (P, Q, violet, 2) diff D: (F, 1, true, orange, 2) label lP: (P, "x=1", orange, 11)
Select the 1.0 in num h: (1.0) and drag left toward zero. Both P and Q update together because they both reference h — the chord rotates in real time until it meets the tangent line drawn by diff. A limit made visible.
num at the top of the script — angles, lengths, positions — and leave the rest of the diagram expressed in terms of them. The whole construction becomes interactive with a single selection.The AI tab.
The AI tab understands GeoScript completely — the full type system, all the syntax rules, how constructions compose. Describe what you want to draw, and it writes the script.
The generated code lands directly in the editor. Every number is adjustable — move a point, change a colour, add a construction on top. The AI writes the scaffold; you make it yours.
BYOK Bring your own API key
GeoScript AI uses your Anthropic API key, pasted once and stored only in your browser. Requests go browser → Anthropic directly — nothing touches our servers. Get a key at console.anthropic.com — no subscription required, costs fractions of a cent per diagram.
Example — geometry.
Triangle with its three classical centres, incircle, and circumcircle.
axes A: ((-5, 5), (-4, 5)) grid G: (A, 1) point P1: (-3, -2, violet, 5) point P2: ( 4, -2, violet, 5) point P3: ( 1, 4, violet, 5) triangle T: (P1, P2, P3, violet, 1.5, violet.alpha(0.07)) circumcircle cc: (P1, P2, P3, teal, 1.5, teal.alpha(0.05)) incircle ic: (P1, P2, P3, orange, 1.5, orange.alpha(0.1)) // Helper types: invisible by default, visible with a colour circumcenter O: (P1, P2, P3, teal, 5) incenter I: (P1, P2, P3, orange, 5) centroid G: (P1, P2, P3, rose, 5) label lO: (O, "circumcenter", teal, 10) label lI: (I, "incenter", orange, 10) label lG: (G, "centroid", rose, 10)
Example — functions.
Two curves, their intersections, and the filled area between them.
axes A: ((-1, 7), (-2, 2)) grid G: (A, 1) ticks T: (A, 1) fn F1: (sin(x), teal, 2) fn F2: (x/3, amber, 2) // Find crossing points — near= picks which one crossing C1: (F1, F2, 0, white, 5) crossing C2: (F1, F2, 3, violet, 5) // Fill region between the crossings integral I1: (F1, C1.x, C2.x, true, teal.alpha(0.2), 1) integral I2: (F2, C1.x, C2.x, true, amber.alpha(0.2), 1) label l1: (C1, "A", white, 11) label l2: (C2, "B", violet, 11)
Note how C1.x and C2.x are used directly as the integral bounds — the crossing type is referenceable as a point, so its coordinates flow naturally into subsequent definitions.