Skip to content
Choose a tag to compare

Ink 1.9 is a backwards-compatible update for the core language, and contains some minor non-breaking changes to the standard library APIs, mostly to improve performance.

Most notably, Ink 1.9 allows expressions in the match target position of a match clause. Previously only "atomic" expressions could be matched against in a list of choices, requiring syntax workarounds like

myValue :: {
    (Type.A) -> doThing()
    (Type.B) -> doThing()
    (1 + 2 + 3) -> doThing()

These expressions may now appear naked in these places:

myValue :: {
    Type.A -> doThing()
    Type.B -> doThing()
    1 + 2 + 3 -> doThing()

Language core

  • 45a8319 Add support for expressions as match clause targets
  • 5d7d5dd Improve number formatting in the language (Prefer formatting numbers in normal form if possible)

Language builtin interfaces

  • fce6f4e Add exit() builtin function
  • 12897e4 Unify copy across runtime error messages
  • def7185 Add env() builtin function

Standard library

  • 7d47f9f suite: When test suite fails, exit(1)
Choose a tag to compare

Ink 1.8 is a backwards-compatible update for the core language, and contains some minor breaking changes to the standard library APIs, mostly to improve performance.

Language core

  • d0f96b1 Binary operators &, |, ^ now support string operations. They perform bitwise operations on strings and return a new string.

Language builtin interfaces

  • 44a5823 runtime: call file.Close() for resources needing closing in read/write/req that used to create a resource leak

Standard library

  • c20772e json: Fix bug that did not escape backslashes correctly in serialization
  • 0f19339 str: Fix bug in str.{hasPrefix?, hasSuffix?} that incorrectly accumulated
  • 35fa1de quicksort: Update quicksort to a cleaner implementation
  • 1124193 std: Use std.append, not join, in flattening list for minimal copying
  • 5e6b788 std: Clean up stdlib, make slice() polymorphic and deprecate sliceList
Choose a tag to compare

Language core

There are no significant changes to language syntax or semantics in this update.

Language builtin interfaces

  • 407fabb Guard against sending invalid HTTP status codes through listen()
  • 98b5f7e Update delete() to delete filesystem nodes recursively
  • 87a1705 Add "mod" to stat() return value
  • 315e7c6 Add "mod" to return value of dir()
  • 828dfd1 Add args() builtin for getting argv[]
  • 861c9df Add urand() for cryptographically safe RNG
  • 822c2ed Update exec() to send event objects, not just output string
  • 6f18152 Update make() to use MkdirAll, not Mkdir (make directories recursively)
  • 8ec1912 Add asin() and acos() to runtime

Standard Library

  • ba75c51: std.writeFile now truncates files before writing them, so writeFile-ing a shorter file will work as expected.
  • 59d0a79 optimization: std.slice now mutates one string instead of creating many, O(n) memory allocation instead of O(n^2)
Choose a tag to compare

This release contains an accumulation of bugfixes to the standard library and some interpreter improvements since the last release. There is one breaking change, which concerns the newly introduced feature of de-duplicated imports added to load('module').


  • exec(command, []args, stdin, outputCallback) is a new builtin function that allows Ink programs to spawn child processes in the operating system and is the primary method of communicating with other software for Ink programs. Access to this API is gated behind the --no-exec and PermissionsConfig.Exec flags.
  • Imports loaded with the load() builtin are now de-duplicated, so only one copy of the imported file is created in one running Context, on first import, which saves memory and allows for multiple files to import the same single single instance of a value.
  • Ink is now available as a Go package, at as package ink.
  • Ink is now continuously tested with Travis CI on master branch and all pull requests.


  • Improvements and bugfixes to std and str standard library functions. In particular, more documentation is added and std.writeFile fixes a bug related to truncating files on save.
  • Ink used to crash when there was an error evaluating the left side of an assignment, or when there were certain syntax errors in composite literals. Both of these now result in an Ink runtime error instead.
Choose a tag to compare

This release is mostly a minor bugfix update. Since I'll be taking a break from working on Ink for a little bit to tend to other projects. I wanted to get all the accumulated fixes out of the gate and released.


  • read() now returns the correct empty value (empty string) when called with --no-read; before, it was returning ().
  • Tests now check for more cases in isolated execution modes, so there should be less regressions around permissions in filesystem or network operations.
  • Sometimes, builtin functions like read were calling the callback twice with conflicting data when errored. This has been fixed, so all builtins now only callback once.
  • The interpreter now correctly deals with io.EOF in the interactive REPL, rather than showing an error when exiting with Ctrl+D.
  • Sometimes, HTTP APIs listen() and req() would return () on empty response bodies instead of the empty string. This has been standardized around the empty string, and all exceptions to this rule have been fixed to use the empty string to represent empty bodies.
  • Fixed some bugs around mutable strings, and when strings are copied vs. mutated.

Other misc

  • The Go code has been refactored around more blocking APIs, dramatically simplifying the overall API around the parser and interpreter.
  • Updated test runner samples/ to have test descriptions for easier debugging on failing tests.
Choose a tag to compare

This release is a major update with some breaking changes, that brings a new interface for builtin system interfaces and comes with an expanded set of standard library capabilities. You can try it at

Go interfaces

  • Simplified Go API with blocking methods -- especially Context.Exec
  • Interpreter core APIs accept io.Reader

Builtin interface overhaul

  • Ink's string type is now just a binary byte array, capable of holding any binary data. like Lua strings.
  • Ink's builtin functions that interface with the network and filesystem now represent binary data and files with Ink strings, which contain the binary data. This makes all operations that interface with these builtins orders of magnitude faster.
  • dir(), stat(), and make() builtins for filesystem operations
  • Much more correct behavior for existing filesystem builtins read() and write()


  • Updated standard library with optimizations
  • Removed the is operator
  • JSON serializer/deserializer in samples
  • Fixed stringification issues with strings that contain escaped characters
  • Refactored internal types to be more consistent / simpler.
Choose a tag to compare

This is the third preview release of Ink. The language specification has stayed unchanged, and the interpreter comes with these improvements.

  • The listen(host, handler) builtin function for starting HTTP servers written in Ink
  • Optimizations to composite value accesses and number-to-string conversions
  • A more stable parser, especially when parsing partial input in the -repl
  • Optimized functions in the standard library, specifically work to make std.encode faster and bug fixes to std.readFile and std.writeFile
  • Support for using the ink interpreter in an Ink script's #!/usr/bin/env ink shebang line
  • General other minor bug fixes and optimizations

You can once again go to to try the newest version of the interpreter, minus file read/write operations and the new listen(...) builtin -- those are limited by the -isolate interpreter flag.

Choose a tag to compare

The patch release brings a bunch of improvements to many different areas in the language and interpreter.

  • Completely redesigned and reworked concurrency model for running Ink functions asynchronously, in a way that leaves more room for future growth and allows multiple asynchronous tasks to be running side by side.
  • An execution context now locks for better memory safety.
  • Fixes and improvements for old samples, and a bunch of new samples in the repository.
  • Building blocks of a module system, using the load() built in function that loads other Ink programs as module objects.
  • New builtin functions in(), read() and write()
  • In addition, a whole class of bugs around concurrency has been fixed!

You can also go try Ink programs on the web now, at

Choose a tag to compare

Ink release!


This is the first release of the Ink interpreter 🚀

echo "out('Hello, World!')" | ink

This is a preview release, because...

  1. although the interpreter core is feature complete, it's missing many builtin functions and features I'd like the basic runtime to have
  2. the language specification may yet change in major ways

That said, this is a fully functional release capable of running all sample programs and tests in the project repository, and implements the full language syntax and semantics including tail recursion optimization.

This release is also designed to be free of crashes and panics. I've been hoping to set up fuzz testing using go-fuzz but haven't had the chance yet -- so if you can make it crash, it's a bug! Please file an issue with a test case 🐞.