Fork me on GitHub

Ѧ simple laחguagέ
ഽor ƩveЯyone

Citrine is a simple programming language that's easy to learn and use. It's so simple, it does not even have special constructs for loops and conditions. Everything is done by sending messages to objects. You can learn Citrine in a couple of minutes!
Latest news | API | Install Icons
☞ f := Array ← 0 ; 1.

0 to: 12 step: 1 do: {

   #take the last element of f
   ☞ a := f last.
   #take the element before that
   ☞ b := f secondLast.
   #write them down
   ✎ write:
      'the sum of ❲ a ❳ and ❲ b ❳'.
   #calculate the sum
   ☞ sum := (a + b).
   ✎ write: 
      ' is ❲ sum ❳ '.

   # add the sum to the array
   f add: sum.

Download Citrine 0.7.7 download citrine
the sum of 1 and 0 is 1
the sum of 1 and 1 is 2
the sum of 2 and 1 is 3
the sum of 3 and 2 is 5
the sum of 5 and 3 is 8
the sum of 8 and 5 is 13
the sum of 13 and 8 is 21
the sum of 21 and 13 is 34
the sum of 34 and 21 is 55
the sum of 55 and 34 is 89
the sum of 89 and 55 is 144
the sum of 144 and 89 is 233
the sum of 233 and 144 is 377

Learn Citrine in one minute

In Citrine, everything is an object. You write a program by making these objects talk to each other, by sending messages.

There are 5 literal objects: Nil, Booleans (True,False), Numbers (i.e. 1,2,3.5,100 and so on), Strings (any text between 'single quotes') and code Blocks: { :parameter1 :parameter2 ...code... }.

Some other rules: you can assign a value to variable using :=, comments start with a # and every line ends with a dot (.).

☞ x := 3 factorial. #x = 6
☞ x := 3 factorial factorial. #x = 720

Here we send the message 'factorial' to 3, the resulting value (6) gets assigned to x (we use the hand for that, the keyword 'var' is also allowed). On the second line we chain two messages (factorial), resulting in x = 720. A keyword message is a message with arguments:

☞ x := 3 between: 1 and: 10. #True
☞ x := 2 + 3. #5

A message that is just one single symbol (+-/*) is a binary message and always has exactly one argument, the object that follows. You can chain keyword messages with a comma (,):

✎ write: 'hello ', write: 'world'.
hello world


Control Flow

To create a loop, send the message 'times:' to a number together with a block of code:

3 times: { :i ✎ write: i. }. #prints: 012

This will run the block of code 3 times. To break out of a loop use break (and continue to skip remainder of the current iteration), the following loops prints: 98765. Also note that we compare using = not ==.

9 to: 0 step: -1 do: { :i 
	✎ write: i. ( i = 5 ) break.

To compare things, send messages like ifTrue: or ifFalse: to expressions that result in boolean values:

☞ ⛁ := 4.
☞ ☕ := 2.5.
(⛁ ≥ ☕) ifTrue: {
	✎ write: 'Buy coffee'.
}, else: {
	✎ write: 'Too expensive'.

You can catch errors by attaching a catch block to your code:

{  2 / 0. } catch:
{ :error ✎ write: error. }, run.
Division by zero.

Craft your own Objects

You can give a block of code a name:

☞ echo := { :x ↲ (x + x). }.
✎ write: (echo applyTo: 'hi'). #hihi

To create your own object and make it respond to messages:

Cat := Object new.
Cat on: 'name:' do: { :n ⚿ name := n. }.
Cat on: 'name' do: { ↲ ⚿ name. }. 

This creates a cat object that responds to 'name:' and 'name' to respectively set and get its name. The object stores its name in a property 'name'. To access a property use or 'my'. Usage:

cat := Cat new.
cat name: 'Diva'.
✎ write: cat name. #prints Diva

If you want to reuse old code, base your object on a previously crafted one (this is called prototypal inheritance):

RoyalCat := Cat new.
RoyalCat on: 'name' do: { :n
	↲ 'your royal highness ' + ( ⛏ `name ).

Here, we override the behaviour for message 'name' with a new response. The symbol 'plays' back another response from the same object. To reference an overridden one prefix the message with a backtick (`).

✎ write: ((RoyalCat new name: 'Diva') name).
your royal highness Diva

Tips & Tricks

Use ❲ ❳ to embed a variable in a string (string interpolation):

☞ name := 'Santa'.
✎ write: '❲name❳ comes to town'.
Santa comes to town

You can modify existing objects (mallable objects), for instance, to make numbers respond to × :

Number on: '×' do: { :b ⛏ times: b. }.
7 × { :i ✎ write: i. }.

You can make objects respond to arbitrary messages (generic responses) as well:

echo := Object new.
echo on: 'respondTo:' do: { :s ↲ 2 × :s }.
echo ho!. #ho!ho!

Citrine uses dynamic scoping:

☞ f := { q := 2. }.
{ ☞ q := 1. f run. ✎ write: q. } run. #prints 2

For the fans of functional programming:

☞ multiplier := { :m 
	↲ { :x 
		↲ (⚿ f * x).
	} set: 'f' value: m.
☞ double := multiplier applyTo: 2.
☞ q := double applyTo: 9. #yields 18


Where can I find more documentation?

All documentation can be found in the man files. You can also consult the online manual pages.

Why does Citrine use icons in the language?

Citrine simply makes use of the possibilities of utf-8. Icons are more descriptive than abbreviations like 'var', they are quicker to type (once you configured your editor), language agnostic (can be used in Dutch source code as well) and allow more natural looking texts (in case of the thin space vs camelCase).

Why has Citrine no built-in functionality X?

Citrine is a minimalist language. The Citrine project focuses on producing a better language. You can add new functionality by using a plugin. Plugins are automatically loaded as soon as you start talking to the object. Put your plugins here:


Some 3rd party plugins: Plugin: JSON (by Jake Russo), Plugin: CURL (by Jake Russo)

In line with the UNIX philosophy you can also invoke other programs to perform certain tasks using the shell:

✎ write: (💻  shell: 'ls -la').

This will print the contents of the current working directory on the screen. You can use the Slurp object to mix other languages (like shell) with Citrine. Every message you send to the Slurp object gets absorbed into a string, the obtain message returns the resulting string, example:

✎ write: (💻  shell: (Slurp ls: '-la', obtain)).

This allows for a more natural notation.

How can I use the icons in the examples?

Install the font that resides in the package 'Citrine.ttf'. Now configure your editor as follows (I use Geany and Geany Macros a macro package for Geany is included ):

cp ~/.config/geany/plugins/Geany_Macros/settings.conf ~/.config/geany/plugins/Geany_Macros/settings_backup.conf

cp macros.ini ~/.config/geany/plugins/Geany_Macros/settings.conf

icon code keys ascii
2264ALT+< or ALT+L<=:
2265ALT+> or ALT+M>=:
2684ALT+/ (? but without shift)Dice
2022ALT+*Short Slurp*

* = use like this: ✎ write: • hello (will convert message hello to string 'hello').

Trick: Use the thin space (2009) to form messages with a space. For instance:

(coffee < 10) if true: { ✎ write: 'refill'. }.


Can I use Citrine to write webapps?

Yes, Citrine ships with a CCGILIB based HTTP plugin (mods/request/ that allows you to deal with GET and POST requests. you can use the Request object like this:

get  := Request get: 'search'.
list := Request getArray: 'orders[]'.
post := Request post: 'message'.
list := Request postArray: 'orders[]'.
file := Request file: 'avatar'.

Storm Server is a CCGILib based SCGI server for Citrine for hi-traffic web applications, to start an instance of Storm we put the following code in storm.ctr:

#Citrine Storm Server Demo storm.ctr
#Put your Citrine scripts in /var/www/htdocs/...
#To kill this server
#kill $(cat /var/run/
Pen write: 'Start Citrine Storm Server v1', brk.
Request host:'localhost' listen:4000 pid:'/var/run/' callback: {
	#Now set the content type and any other headers
        Pen write: 'Content-type: text/html\n\n'.
	#Load the script file
	var fname := Command env: 'DOCUMENT_URI'.
        var script := File new: '/var/www/htdocs' + fname.
        #Run it!
	script include.


Can I serve Citrine applications with NGINX?

Sure, add the following configuration lines to: /etc/nginx/nginx.conf:

location ~ \.ctr$ {
        try_files $uri $uri/ =404;
        include   scgi_params;


Have another question?
Visit Citrine Programming Language Forum!
There you can talk to other Citrine community members, ask questions, discuss new features, issues, bug reports and so on.

Citrine Support Contract Light € 39,-

gaborsoftware GaborSoftware offers various support contracts for the Citrine Programming Language. Benefits of a support contract include: priority status on github, a sponsor logo on the partner page and access to closed source plugins (like GTK plugin) when available. With a Citrine Support Contract Light you also show your support for this project to the rest of the Citrine community. You can get a Citrine Support Contract Light for just € 39,- a year.

The Citrine Programming Language is a product of GaborSoftware © copyright 2018 all rights reserved. Citrine Programming Language created by Gabor de Mooij and the Citrine community. In-language (citrine.ttf) icons from the ionicons project (MIT licensed), FontAwesome (SIL OFL 1.1) by Dave Gandy - and Typicons by S. Hutchings (SIL Open Font Licence).
Website and photography by Gabor de Mooij. Book icon from WikiMedia Commons Project. 'Citrine in a box' icon created by Gabor de Mooij using multiple assets from the WikiMedia Commons Project.
Citrine respects your privacy and does not use cookies. For details read the Citrine Privacy Statement.