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.
Dev Server (quill serve)
What it does
quill serve starts a development server with hot reload. When you save a .quill file, the browser automatically refreshes with your latest changes. It also supports file-based routing, so your file structure becomes your URL structure.
When to use it
Use quill serve when you are building a web application and want to see changes instantly. It replaces the need for tools like webpack-dev-server or Vite.
Step-by-step usage
Step 1: Navigate to your project folder in the terminal.
Step 2: Run the dev server.
quill serve
Step 3: Open http://localhost:3000 in your browser. Edit any .quill file and the page updates automatically.
File-based routing
Place files in a pages/ directory and they become routes automatically:
-- pages/about.quill -> /about
-- pages/blog/[id].quill -> /blog/:id
-- pages/index.quill -> /
Dynamic segments use square brackets. Inside your file, the parameter is available as a variable:
-- pages/blog/[id].quill
to load request:
post is await DB.find({id: request.params.id})
give back {post: post}
to render data:
h1 data.post.title
p data.post.body
Tips
- The server runs on port 3000 by default. Change it with
quill serve --port 8080. - Hot reload works for both server-side and client-side code.
- Use the
style:block in your components for scoped CSS that is automatically hashed.
Full-Stack Mode (quill run)
What it does
Quill can run a single file that contains your server, database, and UI all in one. No configuration, no package.json, no node_modules, no webpack. The compiler reads the server:, database:, and component: blocks and wires everything together.
When to use it
Use this for prototypes, internal tools, weekend projects, or any time you want the fastest path from idea to running app.
Example
server:
port is 3000
route get "/api/users":
users is await DB.find({})
respond with users
database:
connect "sqlite://app.db"
model User:
name as text
email as text
component App:
state:
users is []
to render:
h1 "My App"
for each user in users:
p "{user.name}"
mount App to "#app"
Run it:
quill run app.quill
That is it. One file, one command, full-stack application.
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
-- Watch mode: automatically re-run tests when files change
quill test --watch
-- Watch a specific file
quill test math.quill --watch
-- Short flag
quill test -w
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. - Use
--watchmode during development: This automatically re-runs your tests every time you save a file, giving you instant feedback as you code.
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.
Project Scaffolding (quill new)
What it does
quill new creates a brand-new project directory with a starter file and a quill.toml configuration file. It sets up everything you need to start coding immediately.
When to use it
Use quill new when you want to start a fresh project from scratch. It saves you from manually creating directories and boilerplate files.
Step-by-step usage
Step 1: Run the command with your project name.
quill new my-app
Step 2: Quill creates the directory, writes a main.quill with a hello world program, and writes a quill.toml with project configuration.
Example output
$ quill new my-app
Created project "my-app"
my-app/main.quill
my-app/quill.toml
cd my-app && quill run main.quill
Next steps: Now enter your new project directory and run it: cd my-app && quill run main.quill. You should see "Hello, Quill!" printed to the console.
The generated main.quill contains a simple hello world program:
say "Hello, Quill!"
The generated quill.toml contains your project configuration:
[project]
name = "my-app"
version = "0.1.0"
Tips
- Use
quill newfor quick starts: It creates a new directory with everything set up. If you already have a directory you want to turn into a Quill project, usequill initinstead — it initializes the current directory in place without creating a new one. - Customize the starter file: The generated
main.quillis a simple hello world — replace it with your own code to start building.
Instant Sharing (quill share)
What it does
quill share creates a shareable URL that opens your code in the Quill online playground. The code is base64-encoded in the URL — no server needed.
When to use it
Use quill share when you want to:
- Share code snippets with friends or colleagues
- Ask for help and include a runnable example
- Show off your projects with a single link
Step-by-step usage
Step 1: Run the command with the file you want to share.
quill share app.quill
Step 2: Quill generates a shareable link and copies it to your clipboard.
$ quill share app.quill
Shareable link:
https://quill.tradebuddy.dev/playground#code=...
Link copied to clipboard!
Step 3: Send the link to anyone. When they open it, the playground loads your code automatically.
How it works
The file content is base64-encoded and appended to the playground URL as a hash fragment. When someone opens the link, the playground decodes the hash and loads the code. Nothing is stored on a server — the entire source code lives in the URL itself.
Tips
- Keep files small: The link contains your entire source code, so keep it under a few KB for best results.
- Works offline: The link works even without an internet connection to a backend, since the code is in the URL itself, not stored on a server.
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.
LSP Server (quill lsp)
What it does
LSP stands for Language Server Protocol. It is a standard way for a programming language to talk to your code editor. When you start the Quill LSP server, your editor gains superpowers: it can highlight errors as you type, show documentation when you hover over a function, and suggest completions while you write.
What it provides
- Real-time error highlighting — red underlines appear the moment you make a mistake, before you even save the file.
- Hover documentation — hover over any standard library function to see what it does, what arguments it takes, and what it returns.
- Autocomplete — start typing a function name or keyword and the editor suggests completions for you.
How to start
quill lsp
You normally do not run this command yourself — your editor starts it automatically once configured.
Using with VS Code
Add the following to your VS Code settings.json:
{
"quill.lsp.enabled": true,
"quill.lsp.path": "quill"
}
After reloading VS Code, open any .quill file and you will see errors, hover info, and completions immediately.
LLVM / Native Compilation (quill build --llvm)
What it does
By default, Quill compiles your code to JavaScript. With the --llvm flag, Quill instead produces LLVM IR (Intermediate Representation) — a low-level format that can be compiled into a native binary that runs directly on your operating system, without needing Node.js at all.
How to build
quill build app.quill --llvm
This produces an .ll file containing the LLVM IR. If the LLVM tools llc and a C compiler (cc) are available on your system, Quill will automatically compile the IR into a native executable as well.
When to use it
- Performance-critical code — native binaries start faster and can run computations more efficiently than JavaScript.
- Standalone distribution — ship a single binary to users without requiring them to install Node.js or Quill.
llc is not found, Quill will still produce the .ll file — you can compile it yourself later.
Package Registry
What it does
The Quill package registry lets you share your own packages and use packages written by others. It works together with your project's quill.json file, which lists the packages your project depends on.
Publishing a package
To share your package with the world:
quill publish
This bundles your project and uploads it to the Quill package registry. Make sure your quill.json has a name and version field before publishing.
Searching for packages
quill search <query>
For example, quill search http will show all packages related to HTTP.
Installing dependencies
quill install
This reads your quill.json, resolves all listed dependencies, and downloads them into your project.
Version bumping
Before publishing a new version, bump the version number in quill.json with one command:
quill bump patch -- 1.0.0 -> 1.0.1
quill bump minor -- 1.0.0 -> 1.1.0
quill bump major -- 1.0.0 -> 2.0.0
quill add <package> to install a single package and add it to your quill.json in one step. Use quill install when you clone an existing project and need to fetch all its dependencies.
Debugger (quill debug)
What it does
quill debug lets you run your program one step at a time, pausing wherever you want to inspect what is happening. Think of it like watching a movie in slow motion, you can pause, look around, and then continue.
When you start the debugger, you get an interactive prompt (called a REPL) where you can type commands to control how your program runs.
When to use it
Use the debugger when your program is not behaving the way you expect and you want to see exactly what is happening at each step. Instead of sprinkling say statements everywhere, the debugger lets you pause the program and look at every variable, function call, and line of code as it runs.
Starting the debugger
quill debug main.quill
This opens your program in the debugger. The program does not run immediately, it pauses at the first line and waits for your instructions.
Debugger commands
Once inside the debugger, you can use these commands:
| Command | What it does |
|---|---|
break <line> | Set a breakpoint at a specific line number. The program will pause when it reaches that line. |
step | Run the next line of code and pause again. If the line calls a function, it skips over the function (stays at the same level). |
into | Like step, but if the line calls a function, it goes inside that function so you can see what happens in there. |
out | If you are inside a function, run the rest of it and pause when you return to the caller. Like saying "finish this function and come back." |
continue | Resume running the program normally until it hits the next breakpoint or finishes. |
print <expr> | Show the current value of a variable or expression. For example: print user.name |
locals | Show all local variables and their current values in the current scope. |
stack | Show the call stack, the chain of function calls that led to where you are now. |
list | Show the source code around the current line so you can see where you are. |
quit | Exit the debugger and stop the program. |
Example debug session
Suppose you have this program in math.quill:
to add a, b:
result is a + b
give back result
answer is add(3, 5)
say answer
Here is what a debug session looks like:
$ quill debug math.quill
Quill Debugger v1.0
Paused at line 5
> break 2
Breakpoint set at line 2
> continue
Hit breakpoint at line 2 (inside function "add")
> print a
3
> print b
5
> locals
a = 3
b = 5
> step
Paused at line 3
> print result
8
> stack
add (line 3)
<main> (line 5)
> continue
8
Program finished.
continue. The program will pause at each one in order. This is great for checking values at specific points in your code.
Test Coverage
What it does
Test coverage shows you how much of your code is actually tested. It highlights which lines, functions, and branches your tests exercise, and which ones they miss. This helps you find blind spots and write more thorough tests.
Step-by-step usage
Print a coverage summary:
quill test --coverage
This runs all your tests and prints a table showing the percentage of lines covered in each file.
Generate an HTML report:
quill test --coverage-html
This creates a coverage/ folder with a browsable HTML report. Open coverage/index.html in your browser to see exactly which lines are covered (green) and which are not (red).
Enforce a minimum threshold:
quill test --coverage-min 80
If overall coverage drops below 80%, the command exits with an error. This is useful in CI pipelines to prevent coverage from slipping.
Profiler (quill profile)
What it does
The profiler runs your program and measures how long each function takes. When it finishes, it prints a timing report sorted by total time. This helps you find slow spots in your code so you know where to focus optimization efforts.
Step-by-step usage
quill profile app.quill
You will see output like this:
Function Calls Total (ms) Avg (ms)
------------------------------------------------------
fetchUsers 12 842.3 70.2
processData 12 231.5 19.3
renderPage 12 45.1 3.8
main 1 1120.4 1120.4
Workspaces
What they do
Workspaces let you manage multiple related packages in a single repository (a "monorepo"). Instead of maintaining separate repos for your core library, web app, and CLI tool, you keep them all together and share code between them.
Setting up a workspace
Add a [workspace] section to your root quill.toml:
[workspace]
members = ["packages/core", "packages/web", "packages/cli"]
Each member directory has its own quill.toml and source files. Commands like quill test and quill build can run across all members at once:
-- Test everything in the workspace
quill test --workspace
-- Build everything
quill build --workspace
Migration Tool (quill fix)
What it does
quill fix automatically rewrites your code when you upgrade to a newer version of Quill. If function names changed, syntax was updated, or import paths moved, the migration tool handles it for you.
Step-by-step usage
quill fix --from v0.1 --to v0.3
This scans all .quill files in your project and applies the necessary transformations. It shows a summary of changes made:
Fixed 3 files:
src/main.quill - renamed map() to map_list() (2 occurrences)
src/utils.quill - updated import path "helpers" to "stdlib/helpers"
src/app.quill - replaced deprecated `catch:` with `if it fails:`
quill fix, so you can review the changes and revert if needed.
Project Config (quill.toml)
What it does
When your project grows beyond a single file, you will want a configuration file to keep things organized. The quill.toml file is where you describe your project, its name, version, dependencies, build settings, and more. Think of it like the label on a box: it tells everyone (and the tools) what is inside and how to handle it.
Full example
Here is a complete quill.toml showing all available sections:
# Project metadata
[project]
name = "my-app"
version = "1.0.0"
description = "A cool Quill application"
author = "Your Name"
license = "MIT"
entry = "src/main.quill"
# Build configuration
[build]
target = "node" # "node", "browser", or "standalone"
outDir = "dist" # where compiled files go
sourcemap = true # generate source maps
minify = false # minify the output
# Dependencies
[dependencies]
lodash = "^4.17.0"
express = "^4.18.0"
# Test configuration
[test]
pattern = "tests/**/*.quill" # where to find test files
timeout = 5000 # max time per test in ms
parallel = true # run tests in parallel
# LSP (editor integration) settings
[lsp]
formatOnSave = true # auto-format when you save
checkOnSave = true # run the checker when you save
hoverDocs = true # show docs when you hover over things
You do not need all sections. Start with just [project] and add more as you need them.
Initializing a Project (quill init)
What it does
quill init creates a brand-new Quill project for you. It sets up the folder structure, creates a quill.toml config file, and gives you a starter main.quill file so you can begin coding right away. Think of it like a project template, everything is set up and ready to go.
Step-by-step usage
Step 1: Open your terminal and navigate to where you want your project.
Step 2: Run the init command.
quill init my-project
Step 3: Quill creates the following structure:
my-project/
quill.toml -- project config
src/
main.quill -- your starting file
tests/
main.test.quill -- a starter test file
Step 4: Navigate into the project and start coding.
cd my-project
quill run src/main.quill
quill init without a name to initialize a project in the current directory. Quill will ask you a few questions (name, version, etc.) and create the files for you.
CI/CD (Continuous Integration)
What it is
CI/CD stands for Continuous Integration / Continuous Deployment. In plain English: it means automatically running your tests and checks every time you push code to GitHub. This catches bugs before they reach your users.
Quill has built-in support for GitHub Actions, the most popular CI/CD system for GitHub projects.
How it works
When you create a Quill project with quill init, you can optionally generate a GitHub Actions workflow file. Or you can create one yourself. The workflow file lives at .github/workflows/quill.yml in your project.
Example workflow
# .github/workflows/quill.yml
name: Quill CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install Quill
run: npm install -g @tradebuddyhq/quill
- name: Install dependencies
run: quill install
- name: Check code
run: quill check
- name: Run tests
run: quill test
- name: Build
run: quill build src/main.quill
Every time you push code or open a pull request, GitHub will automatically install Quill, check your code for issues, run your tests, and build your project. If anything fails, you will see a red X on GitHub so you know something needs fixing.
quill check and quill test steps. Add the build step once your project is ready for deployment.
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 build file.quill --llvm |
Compiles to LLVM IR (and optionally a native binary) | quill build app.quill --llvm |
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 debug file.quill |
Starts the interactive debugger for a Quill file | quill debug main.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 lsp |
Starts the Language Server Protocol server for editor integration | quill lsp |
quill publish |
Bundles and publishes your package to the registry | quill publish |
quill search <query> |
Searches the package registry for matching packages | quill search http |
quill install |
Resolves and installs all dependencies from quill.json | quill install |
quill bump patch|minor|major |
Bumps the version number in quill.json | quill bump minor |
quill version |
Shows which version of Quill you have installed | quill version |
quill serve |
Starts a dev server with hot reload and file-based routing | quill serve |
quill profile file.quill |
Runs the profiler and prints a function timing report | quill profile app.quill |
quill test --coverage |
Runs tests and prints a coverage summary | quill test --coverage |
quill test --coverage-html |
Generates an HTML coverage report | quill test --coverage-html |
quill test --coverage-min N |
Fails if coverage drops below N percent | quill test --coverage-min 80 |
quill fix --from X --to Y |
Automated code migration between Quill versions | quill fix --from v0.1 --to v0.3 |
quill deploy |
Generates a Dockerfile and production bundle | quill deploy |
quill db migrate |
Runs all pending database migrations | quill db migrate |
quill db rollback |
Rolls back the last database migration | quill db rollback |
quill db seed |
Seeds the database with sample data | quill db seed |
quill db status |
Shows which migrations have been applied | quill db status |
quill db create <name> |
Creates a new migration file | quill db create add_users |
quill generate <description> |
AI-powered project scaffolding from a description | quill generate "blog" |
quill help |
Shows a summary of all available commands | quill help |
Deployment (quill deploy)
What it does
quill deploy takes your project and generates everything you need to deploy it to production: a multi-stage Dockerfile, an optimized bundle with minified assets, and a startup script. Think of it as packaging your app into a box that any server can open and run.
When to use it
Use quill deploy when you are ready to put your application on a real server — whether that is a cloud provider, a VPS, or your own machine running Docker.
Step-by-step usage
Step 1: Navigate to your project directory (the one with quill.toml).
Step 2: Run the deploy command.
quill deploy
Step 3: Quill generates a Dockerfile and a dist/ folder with your production bundle.
$ quill deploy
Generated Dockerfile
Built production bundle in dist/
Ready to deploy!
Step 4: Build and run the Docker image.
docker build -t my-app .
docker run -p 3000:3000 my-app
dist/ folder contains a standard Node.js application. You can deploy it directly with node dist/index.js on any server that has Node.js installed.
Database Migrations (quill db)
What are migrations?
A migration is a small file that describes a change to your database — like adding a new table, renaming a column, or creating an index. Migrations let you evolve your database over time in a controlled, repeatable way. Think of them as version control for your database schema.
Available commands
quill db create <name>— Creates a new migration file with a timestamp and the name you provide.quill db migrate— Runs all pending migrations that have not been applied yet.quill db rollback— Undoes the last migration. Useful when you made a mistake.quill db seed— Populates the database with sample data for development and testing.quill db status— Shows a list of all migrations and whether each one has been applied.
Step-by-step usage
Step 1: Create a new migration.
$ quill db create add_users_table
Created migrations/20260405_add_users_table.quill
Step 2: Edit the migration file to define your schema change.
to up:
create table "users":
id as number, primary key
name as text
email as text, unique
to down:
drop table "users"
Step 3: Run the migration.
$ quill db migrate
Running: 20260405_add_users_table
Done. 1 migration applied.
Step 4: Check the status at any time.
$ quill db status
20260405_add_users_table applied
quill db rollback to undo the last migration. The down function in your migration file defines how to reverse the change.
Environment Management
What it does
Environment variables store configuration that changes between environments — like database URLs, API keys, and feature flags. Quill automatically loads .env files so you do not have to set these values manually every time you run your program.
How it works
When you run a Quill program, it looks for a .env file in your project directory and loads the values into the environment. You can also specify which environment to use with the --env flag.
-- .env (default)
DATABASE_URL=sqlite://dev.db
DEBUG=true
-- .env.production
DATABASE_URL=postgres://prod-server/myapp
DEBUG=false
Run with a specific environment:
quill run app.quill --env production
This loads .env.production instead of the default .env.
Accessing environment variables in code
-- Read a variable with a default
debug is env("DEBUG", "false")
-- Require a variable (fails fast if missing)
apiKey is env.require("API_KEY")
-- If API_KEY is not set, your program stops immediately with a clear error message
.env to your .gitignore. Use .env.example (with placeholder values) to document which variables your project needs.
AI Scaffolding (quill generate)
What it does
quill generate creates a complete project structure from a short description. Instead of setting up files, routes, models, and configuration by hand, you describe what you want and Quill generates it for you.
When to use it
Use quill generate when starting a new project or adding a major feature. It gives you a working starting point that follows best practices, so you can focus on customizing the logic instead of writing boilerplate.
Available templates
quill generate "blog" -- Blog with posts, comments, markdown rendering
quill generate "api" -- REST API with routes, models, validation
quill generate "chat" -- Real-time chat app with WebSockets
quill generate "crud user" -- Full CRUD endpoints for a model
quill generate "auth" -- Login, register, JWT, sessions
quill generate "dashboard" -- Admin dashboard with charts and tables
Step-by-step usage
Step 1: Run the generate command with a description.
$ quill generate "blog"
Creating blog project...
Created main.quill
Created models/post.quill
Created models/comment.quill
Created pages/index.quill
Created pages/post/[id].quill
Created quill.toml
Done! Run "quill serve" to start.
Step 2: Start the dev server and explore what was generated.
quill serve
Step 3: Customize the generated code to fit your needs. The generated files are standard Quill code — there is nothing special or locked about them.
quill generate "recipe sharing app with user profiles" and Quill will do its best to scaffold something useful.
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.