Appendix C: Version History
What changed in each version of Quill. The newest version is at the top.
Unreleased
Changes that are finished but not yet in a release.
- This book is published at https://ngwangshalom.github.io/Quill/, tested and updated after every change to it. The
QUILL.mdin each new project links there.
v0.4.8 (3 November 2026)
- In VS Code and Cursor, Quill’s colors and the feather work in Restricted Mode, in a folder the editor doesn’t trust yet; before, the editor turned Quill off there. Underlining mistakes starts once the folder is trusted, because it runs the
quillprogram. Quill code in a```quillblock inside a Markdown file, such as a README, has Quill’s colors too. quill new shop appmakes a whole app for a small events company: a backend with bookings read from a file and checked against a type, prices with VAT and payments that add up to the cent, an AI assistant whose answer is checked too, and tests. Without an AI key, everything works except the assistant, which answers 503. It sits at the top of the menu, under “Everything”. Every line of the menu now fits an 80-column terminal.- Quill no longer prints “Quill added colors and the feather icon…” after a command. It still sets up Cursor and VS Code the same way, quietly; reload the editor window after installing or updating Quill to see the colors.
- On Windows, the files
quill newmakes have the same line endings as on macOS and Linux.
v0.4.5 (3 November 2026)
- Templates for
quill new.quill new shopasks what kind of program it is, with the arrow keys, andquill new shop backendskips the menu. Eleven templates, in five groups:learnandstarterfor learning;backend,integrationandwebhookfor backend work;aiandai-backendfor AI;financeandbankingfor business and finance;automationandlibraryfor automation and general programs. Each one runs and passes its tests straight away, and comes with aREADME.mdandQUILL.md, a one-page tour of the language. With no terminal,quill new shopmakesstarter. A misspelled template names the one you meant. trim (parts at 1), with a space before the bracket, is the text tool.trim(x), right against the bracket, calls a function calledtrim; when there is none, Quill explains that the tool takes no brackets.- Working with text.
trim nametakes away the spaces at the ends, anduppercaseandlowercasechange the letters.length of namecounts the letters, withéas one.email contains "@",code starts with "INV", andfile ends with ".csv"are true or false, and work in awhenand awhere;hobbies contains "coding"looks in a list.replace "-" with " " in codechanges every-.split line by ","cuts text into a list, andjoin names with ", "puts a list back into one text. An empty separator is a mistake. None of these words is reserved, sovar length = 0andfn join(...)still work. They are ink (#949CF5on a dark editor,#3A44A0on a light one). - The examples in this book have the editor’s colors: the light ones on the Quill, Light and Rust themes, and the dark ones on Coal, Navy and Ayu. Before, the book’s code was one color, and the code after the first Quill example on a page wasn’t colored at all. In Cursor and VS Code, the second number of a range such as
0..100is colored like the first.
v0.4.2 (3 November 2026)
- How many, the average, and in order.
count of studentssays how many records there are, andcount of students where score >= 50counts the ones that match, with no counter in a loop.average score of studentsis the sum divided by how many; a missing amount is left out, money is rounded to cents, half to even, and an average of nothing stops with a problem that says to check the count first.students sorted by scoreputs the lowest first,sorted by highest scorethe highest, and text goes in alphabetical order; records with the same value keep their order.sorted byworks afterwhereand infor.count,average, andsortedare words only beforeof, a field andof, andby, sovar count = 0andfn average(...)still work. They are sea, likegetandsum. In Cursor and VS Code,get,sum, andwithhad lost their color, because the AI model’sasktook their place in the color list; in Emacs they showed theaskcolor. Each kind has its own color again. - Quill files end in
.quill..qlwas already GitHub’s extension for CodeQL, so GitHub counted Quill files as CodeQL.quill newmakeshello.quill,bring billingreadsbilling.quill, and the editors color.quillfiles. A.qlfile still runs, with a note asking you to rename it (“Note:” in nib orange in a terminal;NO_COLOR=1turns color off), andbringstill findsbilling.ql; a later version will stop reading.ql. quill test shoptests one folder: it runs the files inshopand its subfolders that contain acheckor--- example:. Before, naming a folder was refused as a path without.quill.tryon a line by itself, liketry write_file(...), explains thattrygoes where a call’s answer is used, and showson CantWrite -> fail CantWritefor passing a failure on from a call on its own line. Before, Quill suggestedsay try ..., which can’t work for a call that gives nothing back.- Web services.
bring web, thenroute GET "/hello/{name}"andrespond 200, "Hello, {name}!", turn a program into a web service.{name}parts of the path are values,requestholds the method, path, query and body, and a record is sent as JSON.quill runserves onPORT(8080). Unknown paths get 404, the wrong method 405, and a route that stops 500, with the problem shown and the server still running.routeandrespondare mist, likebring. - Asking an AI model.
bring ai, thenask "Summarize: {text}"gives back the model’s answer, andask "..." as Reviewgives back aReview: the model is sent the type’s shape, and the answer is checked against every field andwhererange.ModelFailedandInvalidare handled like any failure.permit env "ANTHROPIC_API_KEY"chooses Claude (claude-opus-5-5unlessQUILL_AI_MODELsays otherwise);permit env "OPENAI_API_KEY"chooses any OpenAI-compatible service, including one on your own computer.askis spark. - Web requests.
bring httpaddsfetch(url),post(url, body)andsend(method, url, body, headers). Each needspermit netfor the host, gives back an answer withstatusandbody, and fails withNetworkDownwhen the service can’t be reached. A404or500is still an answer, so the program decides. - JSON.
body as Bookingreads JSON text as any kind, checking every field, its kind, and itswhererange; money is read exactly, even from text like"500.00". Text that doesn’t fit fails withInvalid, handled withon Invalidortry.json(value)writes any value as JSON.asis steel, liketype. - Permits, files and settings.
permit read "config",permit write "reports",permit env "STRIPE_KEY"andpermit net "api.stripe.com"say what a program may touch; anything else is refused.read_file,write_file,file_existsandenvare Quill’s own functions, and their failures (FileMissing,CantWrite) are handled withonortry. A path or name written in the call is checked before running, and..can’t leave a permitted folder. A brought file can’t give itself permits.permitis rust. bringputs a program together from files.bring billingreads billing.quill next to the file, andbring "shared/money.quill"reads a file by its path. Its functions and types are used by name; its own tests run when that file is tested. A problem in a brought file names that file. Misspelled names suggest the file you meant; files that bring each other in a circle, a brought file that does something, and a name written in two files are explained.bringis mist blue, the color saved for modules.- Money that never loses a cent.
round total to centsrounds half to even, as banks do;round upandround downchoose a direction, andround x to 2 placesworks on numbers.split 100 USD into 3gives33.34 USD, 33.33 USD, 33.33 USD, andsplit fee by list 70, 30shares by weights; the parts always add up.20% of feetakes a percent.convert 100 USD to EUR at 0.92changes currency at a rate you write, and adding two currencies now suggests it. Money is shown in whole units or with every cent (90 USD,7.50 USD), and Quill knows currencies without cents, like XAF and JPY, and with three digits, like KWD.round,splitandconvertare mint. - Types.
type Booking, then one field per line, likeguests: number where 1..500, names what every booking has.Booking venue = "Town Hall", guests = 120, fee = 500 USDmakes one; every field must be there and be the right kind, and each field’s range is checked as it is made. A type works as a kind (b: Booking,-> Booking,list of Booking), and a function that takes one checks the type’s ranges. A misspelled field is reported once.typeis steel, likewhere.
v0.4.0 (20 October 2026)
- Contracts.
require amount > 0 USDunderfnsays what has to be true when the function is called.ensure result >= 0 USDsays what is true each time it gives back, andresultis the value it gives back. A broken one stops the program, names the values it read, and says whose mistake it was; a brokenrequirenames the line of the call.require,ensure, andfailsgo at the top of the function in any order.quill explaindescribes contract lines.require,ensure, andresultinside anensureare brass (#C8A06Aon a dark editor,#7A5A20on a light one). - Ranges with
where.fn book(guests: number where 1..500)takes 1 through 500 guests, both ends included. Money works too:amount: USD where 1 USD..10000 USD. A written value outside the range, likebook(600), is caught before the program runs; any other value stops the call and names the value and the line of the call. Both ends are written values of the parameter’s kind, smallest first.quill explaindescribes the range.whereis steel (#6AA8C8on a dark editor,#1A5270on a light one), the color saved for rules on types. - Filtering with
where.students where score >= 50keeps the records whose condition is true, like Laravel’swhere. Inside the condition a field is read by its name. It works insidegetandsum(sum fee of roster where paid == false), afterfor ... in, and again after itself (where score >= 50 where paid). No match gives an empty list. A misspelled field names the record’s fields. - Asking for data.
sum fee of rosteradds the fee of each record.get fee of rostertakes that field as a list.get name, age, fee of rosterkeeps those fields together on each record. The same line reads one record:get name, fees of schoolis one record with those fields.sum fees of schoolis that one amount. A dot afterofreads a field further in:get place of desk.bookings,get gpa of school.acceptances. Name the record before the dot:first = desk.bookings at 1, thenfirst.place.get bookings with acts in rosteris the longer form, for a list and the field embedded in it. A missing amount is left out of a single field.forremains when each record needs its own step.get,sum, andwithare sea (#6EC1D6on a dark editor,#15556Aon a light one). whengives a value.delivery = when, then indented cases liketotal > 100 -> 0, ending withelse -> 10. The first true case gives the value. It works after=,set,say, andreturn.elseis required, and every case gives the same kind of value.quill explaindescribes each case.oncan carry on.on Declined -> "declined"uses that value in place of the call’s answer, and the program continues.on Declined -> say "..."still runs and then stops. Eachonline chooses for itself.- Examples above a function test it.
--- example: with_vat(100 USD) == 105 USDdirectly abovefn with_vatruns once the function is written, so a function’s documentation and its tests sit together above it. A failed example says “An example”, not “A example”. quill test FILE.qlruns one file. Test reports count executed checks, including functions, loops, and passes before a failure.- Remainder overflow reports a Quill arithmetic problem instead of crashing.
- The README marks the type checker and contracts as implemented.
- The README writes money as
USD, the way Quill does, instead ofMoney<USD>. Contracts stayrequireandensure. Its error andquill explainexamples show Quill’s real output. - Money examples use dollars.
100 USD + 50 USDis150 USD. - Quill’s public description is this: intent is clear, failures are explicit, and correctness is part of the code. It is for backend engineering, financial software, automation, reliable business applications, and AI and machine learning. Asking a model and training one are part of that. Operating systems, device drivers, and 3D games stay with Rust and C++.
v0.3.1 (14 October 2026)
- Indentation is exact. A block moves in by 2 spaces. A tab, or any other width, is a mistake.
- A range is two dots.
18...25is a mistake, and Quill tells you to write18..25.->belongs inside a when, sosaytakes the text directly. - Money.
100 USD + 50 USDis150 USD. Two currencies cannot be added. A function writes the currency as the kind:price: USD. - Maybe.
-> maybe numbermeans the answer might be missing.return found 2.50orreturn missing.whenopens it withfoundandmissing, and both are required.maybe,found, andmissingare peach. - Failures.
fails Declinednames how a function can fail.fail Declinedleaves with that failure. The caller writeson Declinedunder the call, ortryinside a function that fails the same way.fails,fail,on, andtryare red. - Functions.
fn double(n: number) -> numbernames a calculation, andreturngives the value back. A call isdouble(21). A function with no->does work and gives nothing back.fnandreturnare pink. list,record,of, andateach have their own editor color: clay, sage, gold, and violet.- Lists and records.
list "coding", "reading"keeps values in order, andhobbies at 1is the first.recordkeeps named fields, andaddress.cityreads one.for hobby in hobbieswalks a list.atpicks one item, andofis required on an empty list (list of text). The book says where each word is used, and search findsofandat. forloops.for i in 1..3repeats the lines under it for 1, then 2, then 3. Both ends count. The name exists only inside the loop, and the loop moves it to the next number itself. Search in the book findsfor,when,say, and the other Quill words that ordinary search skips.- The book has a Quill theme: warm paper, ink, and a brass mark for the chapter you are reading. Pick it from the paintbrush menu. When your system is set to light, the book opens in Quill.
- The book uses the Quill feather as its icon, in the browser tab and beside the title.
- Quill has its own editor colors, one for each kind of word (
say,when,trueandfalse,varandset,check, and the logic words), the feather on.qlfiles (pale on a dark editor, deep blue on a light one), and underlines for mistakes. Colors for types and the other planned kinds are reserved until those words exist.maybeand failures have their colors now. Cursor and VS Code get them the first time Quill runs. Vim, Emacs, and Sublime detect.qlfiles from theeditorsfolder.quill lspreports the same mistakes to any editor. SetQUILL_NO_EDITOR_SETUP=1to leave Cursor and VS Code alone.
v0.3.0 (13 October 2026)
quill updateshows every version of Quill in a menu: choose one with ↑ ↓ and Enter.quill update latestorquill update 0.2.0installs a version directly, andquill upgradeis another name for the same command.- Quill checks for a new version at most once a day, in the background, and says when one is out. It never updates by itself. Set
QUILL_NO_UPDATE_CHECK=1to turn the check off.
v0.2.0 (13 October 2026)
- Arithmetic with
+,-,*,/and%, brackets, and the usual order of operations. See Numbers and Calculations. - Exact decimal numbers:
0.1 + 0.2is exactly0.3. - Comparisons
==,!=,<,<=,>,>=, and conditions withand,orandnot. - Values inside text:
"Hi {name}". See Text. varandsetfor values that change. See Values That Change.whento choose what to do, with->andelse. See Making Decisions with when.- Indentation marks the cases of a
when. - The checker knows the kind of every value and catches mistakes like
price + "5"before running. checkaccepts any comparison, not only==.quill explaindescribes calculations,var,setandwhen.- New reserved words:
var,set,when,else,true,false,and,or,not.
v0.1.0 (13 October 2026)
The first release.
sayto show a value, andname = valueto name one.- Text in double quotes, with escapes and three-quote text; numbers written exactly as typed.
- Comments (
--) and doc comments (---). - Tests:
check a == band--- example:. - Errors in the README style: where, what, why, and “Did you mean”.
- The
quilltool:run,check,test,explain,new,tokens,help,version. - Installers for macOS, Linux and Windows.