Developer Tools Guide
Quill comes with a full set of built-in tools that help you write, run, check, format, test, and share your programs. You do not need to install anything extra — everything described on this page is included when you install Quill.
This guide walks through every tool step by step. If you have never used a programming tool before, don't worry — each section explains what the tool does, why it exists, and exactly how to use it.
Running Programs (quill run)
What it does
quill run takes a Quill file you have written and executes it immediately. Think of it like pressing "play" on a video — your program runs from top to bottom, and you see the results in your terminal.
When to use it
Use quill run every time you want to try out your code. It is the single most common command you will use. Wrote a new feature? Run it. Fixed a bug? Run it. Just want to see what happens? Run it.
What happens behind the scenes
When you type quill run hello.quill, three things happen in order:
- Translation — Quill reads your
.quillfile and translates the English-like code into JavaScript, a language that computers already know how to run. - Execution — Quill hands that JavaScript to a runtime (by default, Node.js) which actually runs the instructions.
- Output — Anything your program prints (using
say) appears in your terminal.
You never see the JavaScript — it all happens automatically behind the scenes.
Step-by-step usage
Step 1: Create a new file. You can use any text editor. Save it with the .quill extension.
-- hello.quill
say "Hello, World!"
Step 2: Open your terminal and navigate to the folder where you saved the file.
Step 3: Run the program.
quill run hello.quill
Step 4: See the output.
Hello, World!
Example: input and output
Here is a slightly bigger program and what it produces:
Input file (greeting.quill):
name is "Quill"
version is 1
say "Welcome to {name} version {version}!"
say "Today is a great day to learn coding."
Command:
quill run greeting.quill
Output:
Welcome to Quill version 1!
Today is a great day to learn coding.
Running with different runtimes
By default, Quill uses Node.js to run your code. If you have other JavaScript runtimes installed (such as Deno or Bun), you can tell Quill to use them instead:
-- Run with Bun (faster startup)
quill run hello.quill --runtime bun
-- Run with Deno
quill run hello.quill --runtime deno
For most beginners, the default (Node.js) works perfectly. You only need to think about other runtimes if you have a specific reason to use them.
Tips
- If you get an error, read the message carefully — Quill tries to tell you exactly which line has a problem.
- You can run the same file as many times as you like. Each run starts fresh.
- Make sure your file ends in
.quill— Quill will not recognize other file extensions.
Building and Compiling (quill build)
What it does
quill build translates your Quill code into another format without running it. This is called "compiling." Instead of seeing output in your terminal, you get a new file that can be used somewhere else — in a web page, as a standalone app, or as a module for other programs.
What is compiling?
Imagine you wrote a letter in English and need to send it to someone who only reads French. A translator converts the letter into French for you. Compiling is the same idea: Quill translates your English-like code into a language that a specific platform understands.
Quill can compile to four different targets, depending on where you want your program to run:
- Node.js (default) — for running on your computer via Node
- Browser — for running inside a web page
- WASM — for running in any WebAssembly environment
- Standalone — for creating a self-contained program anyone can run
Node.js target (default)
This is the simplest option. It produces a plain JavaScript file that you can run with Node.js.
When to use it: When you want to save the compiled output, share it with someone who has Node.js, or include it in a larger JavaScript project.
Step 1: Build your file.
quill build myprogram.quill
Step 2: This creates myprogram.js in the same folder.
Step 3: You can run the result with Node.js directly.
node myprogram.js
Example:
$ quill build greeting.quill
Compiled greeting.js
$ node greeting.js
Welcome to Quill version 1!
Browser target (--browser)
This compiles your Quill code into JavaScript that works inside a web browser. It gives you access to special browser-only functions for building interactive web pages.
When to use it: When you want to build a website or web app. If your program needs to show things on a web page, respond to button clicks, or save data in the browser, this is the target you want.
Step 1: Write a Quill program that uses browser functions.
-- app.quill
to setup:
heading is select("#title")
setText heading "Welcome to my app!"
onLoad setup
Step 2: Build for the browser.
quill build app.quill --browser
Step 3: Include the output in an HTML file.
<!DOCTYPE html>
<html>
<body>
<h1 id="title">Loading...</h1>
<script src="app.js"></script>
</body>
</html>
Step 4: Open the HTML file in your browser. The heading will change to "Welcome to my app!"
Browser functions: complete reference
When you build with --browser, you get access to the following functions. These do not work in regular Node.js programs — they only work in the browser.
| Category | Function | What it does | Example |
|---|---|---|---|
| Finding elements | select(selector) |
Finds one element on the page by its CSS selector (like an ID or class name) | btn is select("#my-button") |
selectAll(selector) |
Finds all elements that match the selector and returns them as a list | items is selectAll(".item") |
|
| Changing content | setText(el, text) |
Changes the text inside an element | setText heading "Hello" |
setHTML(el, html) |
Changes the HTML inside an element (use with care) | setHTML box "<b>Bold</b>" |
|
getValue(el) |
Gets the current value of an input field | name is getValue(input) |
|
setValue(el, val) |
Sets the value of an input field | setValue input "" |
|
| Styling | addClass(el, cls) |
Adds a CSS class to an element | addClass card "highlight" |
removeClass(el, cls) |
Removes a CSS class from an element | removeClass card "highlight" |
|
toggleClass(el, cls) |
Adds the class if missing, removes it if present | toggleClass menu "open" |
|
hide(el) / show(el) |
Hides or shows an element on the page | hide errorMsg |
|
| Events | onClick(el, fn) |
Runs a function when the element is clicked | onClick btn handleClick |
onInput(el, fn) |
Runs a function when the user types in an input field | onInput search filterList |
|
onKeyPress(el, fn) |
Runs a function when a key is pressed inside an element | onKeyPress input checkEnter |
|
onLoad(fn) |
Runs a function when the page finishes loading | onLoad setup |
|
| Creating elements | createElement(tag) |
Creates a brand new HTML element (like a paragraph, div, or list item) | li is createElement("li") |
append(parent, child) |
Adds a new child element inside a parent element | append list li |
|
| Storage | save(key, val) |
Saves a value to the browser's local storage (persists between visits) | save "username" name |
load(key) |
Loads a previously saved value from local storage | name is load("username") |
|
| Timing | after(ms, fn) |
Runs a function once after a delay (in milliseconds) | after 3000 hideMessage |
every(ms, fn) |
Runs a function repeatedly at a set interval | every 1000 updateClock |
Browser example: a simple todo app
-- todo.quill: a complete todo list for the browser
-- Find the elements on the page
input is select("#todo-input")
button is select("#add-btn")
list is select("#todo-list")
-- This function runs when the user clicks the Add button
to addTodo:
text is getValue(input)
if text is not "":
li is createElement("li")
setText li text
append list li
setValue input ""
-- Connect the button to the function
onClick button addTodo
WASM target (--wasm)
What is WASM?
WASM stands for WebAssembly. It is a special format that runs very fast in web browsers and other environments. Think of it as a universal language that almost any platform can run, similar to how PDF files can be opened by almost any computer.
When to use it: When you need your program to run as fast as possible in a browser, or when you want to use your Quill code inside another system that supports WebAssembly (like game engines or edge computing platforms).
Step 1: Write your program.
-- math.quill
to add a b:
give back a + b
to multiply a b:
give back a * b
Step 2: Build as WASM.
quill build math.quill --wasm
Step 3: This produces a math.wasm file.
$ quill build math.quill --wasm
Compiled math.wasm (WASM module)
The .wasm file can be loaded from JavaScript in a browser or any WASM-compatible runtime.
Tips
- WASM is an advanced feature. If you are just getting started, the default Node.js or browser targets are easier to work with.
- WASM files are very small and load quickly, making them ideal for performance-sensitive applications.
Standalone target (--standalone)
What it does
This creates a single executable file — a program that anyone can run by double-clicking it or typing its name in a terminal. The person running it does not need Quill, Node.js, or anything else installed.
When to use it: When you want to share your program with someone who is not a programmer, or when you want to deploy your program to a server without installing any extra tools.
How it works: Quill compiles your code to JavaScript, then bundles it together with a tiny JavaScript runtime into a single binary. The result is a self-contained executable, just like any other app on your computer.
Step 1: Build as standalone.
quill build myapp.quill --standalone
Step 2: This creates an executable called myapp (or myapp.exe on Windows).
Step 3: Run it directly.
$ quill build server.quill --standalone
Compiled server (standalone executable)
$ ./server
Server running on port 3000
Tips
- Standalone executables are larger than regular
.jsfiles because they include the runtime. This is normal. - The executable is built for your current operating system. A standalone built on a Mac will not run on Windows, and vice versa.
- This is a great way to distribute command-line tools or small utilities to non-programmers.
Formatter (quill fmt)
What it does
The formatter automatically cleans up your code's layout — fixing spacing, indentation, and line breaks — without changing what the code actually does. It is like a spell-checker, but for code style instead of spelling.
Why consistent style matters
When you work on code, especially with other people, inconsistent formatting makes code harder to read. One person might use 4 spaces for indentation, another might use 2. One might put blank lines everywhere, another might squash everything together. The formatter solves this by enforcing one consistent style automatically.
Even if you work alone, formatting your code makes it easier to spot mistakes and come back to your code later.
What the formatter does specifically
- Normalizes indentation to 2 spaces
- Adds blank lines between function definitions and block statements for readability
- Ensures consistent spacing around operators (like
+,-,*) - Converts comparison operators back to English words (
is greater than,is less than) - Formats boolean values as
yesandno
Step-by-step usage
Step 1: Write some code (it is okay if the formatting is messy).
Step 2: Run the formatter on your file.
quill fmt myprogram.quill
Step 3: Open the file again. It will be neatly formatted. The formatter edits the file in place, meaning it overwrites your original file with the cleaned-up version.
Example: before and after
Before formatting:
name is "Sarah"
age is 25
if age > 18:
say "adult"
active is true
to add a b:
give back a+b
After running quill fmt:
name is "Sarah"
age is 25
if age is greater than 18:
say "adult"
active is yes
to add a b:
give back a + b
Notice how the formatter added blank lines between sections, fixed the spacing around +, replaced > with is greater than, and replaced true with yes.
Tips and common workflows
- Format before sharing: Run
quill fmton your files before showing your code to someone else or submitting a project. - Format often: There is no downside to formatting frequently. Many programmers format every time they save a file.
- It is safe: The formatter only changes how your code looks, never what it does. Your program will behave identically before and after formatting.
- Combine with check: A great habit is to run
quill fmtfirst, thenquill checkto catch any real problems.
Type Checker and Linter (quill check)
What it does
quill check reads your code and looks for problems without actually running it. This is called "static analysis" — it analyzes your code while it is sitting still (static), before you press play.
Think of it like a teacher reading your essay and marking potential problems before you submit it. The checker finds bugs, suspicious patterns, and style issues so you can fix them early.
When to use it
Use quill check before running your program, especially when:
- You have written a lot of new code and want a quick sanity check
- Your program is crashing and you want to find the problem
- You want to clean up your code and remove unused variables
Types of issues it catches
- Wrong argument count — You called a function with too many or too few values. For example, if
addexpects 2 numbers but you gave it 3. - Return outside function — You used
give backoutside of atoblock.give backonly makes sense inside a function. - Empty import path — You wrote
use ""with no file path.
- Unused variables — You created a variable but never used it. This usually means you forgot to use it or made a typo. (Prefix with
_to suppress, e.g.,_temp is 5.) - Division by zero — You are dividing by the number
0, which is mathematically undefined. - Self-comparison — You are comparing a variable to itself (
x is x), which is always true and probably a mistake. - Always-true or always-false conditions — Writing
if yes:orif no:means the condition never changes, so the code either always runs or never runs. - Infinite loops — A
while yes:loop with no way to exit will make your program run forever. - Negative array index — Using
items[-1]does not work the way you might expect. - Tests without expectations — A
testblock that never usesexpectwill always pass, which defeats the purpose of testing. - Expect outside test — Using
expectwithout wrapping it in atestblock. - Duplicate properties — Defining the same property or method name twice in a class.
- Lowercase class names — Class names should start with a capital letter. Use
describe Dog:instead ofdescribe dog:. - Functions without return — A function that never uses
give backmight be missing a return value.
Step-by-step usage
Step 1: Run the checker on your file.
quill check myprogram.quill
Step 2: Read the output. Each issue tells you the line number, the severity (error, warning, or info), and a description of the problem.
Step 3: Fix the issues in your code and run quill check again until no issues remain.
Example output with explanations
Found 3 issue(s) in program.quill:
line 2 [warning]: variable "temp" is defined but never used
hint: prefix with _ to suppress this warning
line 8 [error]: add() expects 2 arguments but got 3
line 12 [warning]: division by zero
Here is what each issue means and how to fix it:
- Line 2: You created a variable called
tempbut never used it anywhere. Either use it, remove it, or rename it to_tempif you intentionally want to keep it unused. - Line 8: You wrote something like
add(1, 2, 3), but youraddfunction only accepts 2 arguments. Remove the extra argument. - Line 12: You have something like
result is x / 0. Dividing by zero is not allowed. Check your math.
Tips
- Run early, run often: The sooner you catch a bug, the easier it is to fix.
- Fix errors before warnings: Errors will crash your program. Warnings are less urgent but still worth fixing.
- A clean check does not mean zero bugs: The checker catches common problems, but it cannot find every possible bug. Always test your code too.
Testing (quill test)
What it does
quill test runs all the tests in your Quill files and tells you whether they passed or failed. Tests are small checks you write to make sure your code behaves correctly.
When to use it
Use testing whenever you want to make sure your code works as expected. This is especially useful when:
- You just wrote a new function and want to verify it works
- You changed existing code and want to make sure you did not break anything
- You are working on a project with many parts that need to work together
How to write tests
Tests use two keywords: test to define a test, and expect to check a result.
-- Define a function
to add a b:
give back a + b
-- Test that function
test "add works with positive numbers":
expect add(2, 3) to be 5
expect add(10, 20) to be 30
test "add works with negative numbers":
expect add(-1, 1) to be 0
expect add(-5, -3) to be -8
Step-by-step usage
Step 1: Write your functions and your tests in the same file (or in separate files).
Step 2: Run the tests.
-- Test a single file
quill test math.quill
-- Test multiple files
quill test math.quill strings.quill
-- Test all .quill files in the current folder
quill test
Step 3: Read the results.
Reading test output
When all tests pass, you will see something like:
Running tests...
PASS add works with positive numbers
PASS add works with negative numbers
2 tests passed, 0 failed
When a test fails, Quill tells you exactly what went wrong:
Running tests...
PASS add works with positive numbers
FAIL add works with negative numbers
Expected -8 but got -2
at line 12 in math.quill
1 test passed, 1 failed
The "FAIL" line tells you:
- Which test failed ("add works with negative numbers")
- What the expected result was (-8)
- What the actual result was (-2)
- Where in your code the failure happened (line 12)
Tips
- Give tests descriptive names:
"add works with negative numbers"is much better than"test 2". - Test edge cases: What happens with zero? With negative numbers? With empty strings? These are the places bugs like to hide.
- Run tests after every change: This way you catch problems immediately instead of discovering them later.
- Each
expectshould check one thing: If a test has 10 expects and one fails, it is easier to find the problem when each expect checks a single behavior.
Documentation Generator (quill docs)
What it does
quill docs reads your Quill source file and creates a nicely formatted HTML page that lists all your functions, their parameters, and any comments you wrote to explain them. This is useful for sharing your code's documentation with others (or for your future self).
When to use it
Use quill docs when:
- You are building a library that other people will use
- You want a quick reference for all the functions in a file
- You want to publish documentation for a project
How to write doc comments
Quill uses regular comments (lines starting with --) placed directly above a function as documentation. Write a short description of what the function does and what each parameter means.
-- Calculate the area of a rectangle.
-- width: the width of the rectangle
-- height: the height of the rectangle
to area width height:
give back width * height
-- Greet someone by name.
-- name: the person's name
to greet name:
say "Hello, {name}!"
Step-by-step usage
Step 1: Make sure your functions have comments above them.
Step 2: Run the documentation generator.
quill docs mylib.quill
Step 3: This produces an HTML file in the same directory.
$ quill docs utils.quill
Generated utils.html (3 functions documented)
Step 4: Open the generated HTML file in a browser to see your formatted documentation.
Example: input and output
Input (shapes.quill):
-- Calculate the area of a circle.
-- radius: the distance from center to edge
to circleArea radius:
give back 3.14159 * radius * radius
Command:
$ quill docs shapes.quill
Generated shapes.html (1 function documented)
Output (shapes.html) contains:
- The function name:
circleArea - Its parameter:
radius— "the distance from center to edge" - Its description: "Calculate the area of a circle."
Tips
- Always write a comment above each function, even if it seems obvious. Your future self will thank you.
- Keep descriptions short — one sentence is usually enough.
- Document every parameter so readers know what values to pass in.
Package Manager (quill init, quill add, quill remove)
What it does
The package manager helps you organize your Quill projects and use third-party libraries (pre-written code made by other people). It has three commands:
quill init— starts a new projectquill add— installs a package (library) and adds it to your projectquill remove— uninstalls a package from your project
Starting a new project (quill init)
When you run quill init, Quill creates two files for you:
quill.json— A project file that stores your project's name, version, and a list of packages it depends on. Think of it as a recipe card that lists all the ingredients your project needs.main.quill— A starter file with a simple "Hello, Quill!" program you can run right away.
Step 1: Create a new folder for your project.
mkdir my-app
cd my-app
Step 2: Initialize the project.
quill init
Step 3: See what was created.
$ quill init
Created quill.json
Created main.quill
Step 4: Run the starter program.
$ quill run main.quill
Hello, Quill!
What quill.json looks like
{
"name": "my-app",
"version": "1.0.0",
"dependencies": {}
}
The dependencies section starts empty. When you add packages, they show up here.
Installing packages (quill add)
Quill can use packages from npm (the world's largest collection of JavaScript libraries). This means you have access to hundreds of thousands of pre-built tools.
Step 1: Make sure you have a quill.json file (run quill init first if you do not).
Step 2: Add a package by name.
quill add chalk
Step 3: The package is downloaded and recorded in your quill.json.
$ quill add chalk
Installing chalk...
Added chalk@5.3.0 to dependencies
Your quill.json now looks like this:
{
"name": "my-app",
"version": "1.0.0",
"dependencies": {
"chalk": "^5.3.0"
}
}
Removing packages (quill remove)
If you no longer need a package, remove it to keep your project clean.
Step 1: Run the remove command with the package name.
quill remove chalk
Step 2: The package is uninstalled and removed from quill.json.
$ quill remove chalk
Removed chalk from dependencies
Tips
- Always start with
quill init: Creating aquill.jsonis the first step for any project that uses packages. - Check npm for packages: Visit npmjs.com to browse available packages and find tools for your project.
- Keep dependencies minimal: Only install packages you actually need. Fewer dependencies means fewer things that can break.
- Commit your quill.json: If you use version control (like Git), always include
quill.jsonso others can install the same packages.
Interactive REPL (quill repl)
What is a REPL?
REPL stands for Read, Evaluate, Print, Loop. It is an interactive mode where you type one line of Quill code at a time, and Quill immediately shows you the result. Then it waits for your next line. It keeps going in a loop until you tell it to stop.
Think of it like a calculator: you type something in, press enter, and see the answer right away.
When to use it
- Experimenting: Want to see what
3 + 4 * 2evaluates to? Type it in the REPL and find out instantly. - Learning: When you are learning a new concept, the REPL lets you try things without creating a file.
- Debugging: If you are not sure why a piece of code is not working, try it in the REPL to isolate the problem.
Step-by-step usage
Step 1: Start the REPL.
quill repl
Step 2: You will see a prompt where you can type Quill code.
Quill REPL (type "exit" to quit)
>
Step 3: Type any Quill expression or statement and press Enter.
> name is "World"
> say "Hello, {name}!"
Hello, World!
> 10 + 20 * 3
70
> exit
Tips
- The REPL remembers variables you defined earlier in the session. If you set
x is 5, you can usexin later lines. - Type
exitto leave the REPL and return to your normal terminal. - The REPL is great for quick experiments, but for anything longer than a few lines, use a
.quillfile instead.
All Commands Reference
Here is a complete table of every Quill command. Use this as a quick reference when you know what you want to do but cannot remember the exact command.
| Command | What it does | Example |
|---|---|---|
quill run file.quill |
Runs a Quill program and shows the output | quill run hello.quill |
quill build file.quill |
Compiles to JavaScript (Node.js target) | quill build app.quill |
quill build file.quill --browser |
Compiles for use in a web browser | quill build app.quill --browser |
quill build file.quill --wasm |
Compiles as a WebAssembly module | quill build math.quill --wasm |
quill build file.quill --standalone |
Creates a self-contained executable | quill build app.quill --standalone |
quill fmt file.quill |
Formats your code for consistent style | quill fmt main.quill |
quill check file.quill |
Checks for bugs and style issues without running | quill check main.quill |
quill test |
Runs all tests in the current directory | quill test |
quill test file.quill |
Runs tests in a specific file | quill test math.quill |
quill docs file.quill |
Generates HTML documentation from your code | quill docs utils.quill |
quill init |
Creates a new project with quill.json and main.quill | quill init |
quill add <package> |
Installs a package and adds it to dependencies | quill add lodash |
quill remove <package> |
Uninstalls a package and removes it from dependencies | quill remove lodash |
quill repl |
Starts an interactive session for experimenting | quill repl |
quill version |
Shows which version of Quill you have installed | quill version |
quill help |
Shows a summary of all available commands | quill help |
quill run to run your first program, then explore quill fmt and quill check as you write more code. The other tools become useful as your projects grow.