Projects
A Keel project is a directory containing a keel.toml manifest file. The manifest declares your project's entry point and permissions, so you don't need to pass environment variables or flags on every invocation.
Creating a Project
Use keel init to scaffold a new project:
keel init my-project
This creates a my-project/ directory with a minimal project structure:
my-project/
keel.toml
src/
main.kl
modules/ -- user-defined file modules go here
For a data pipeline scaffold with IO and DataFrame permissions pre-configured:
keel init my-pipeline --template pipeline
Project Manifest
The keel.toml file describes your project:
[project]
name = "my-project"
version = "0.1.0"
main = "src/main.kl"
| Field | Required | Default | Description |
|---|---|---|---|
name | Yes | — | Project name |
version | Yes | — | Project version |
main | No | src/main.kl | Entry point for keel run |
Permissions
Permissions sections control what capabilities your Keel code has access to. All sections are optional — missing sections keep the default behavior.
IO Permissions
[permissions.io]
enabled = true
read_only = false
sandbox = "./data"
| Field | Default | Description |
|---|---|---|
enabled | false | Enable file IO operations |
read_only | false | Restrict to read-only file access |
sandbox | — | Restrict IO to this directory (relative to project root) |
With IO enabled, you can read JSONL files and parse them in a pipeline:
import IO
import Jsonl
import Result
IO.readFile "data/events.jsonl"
|> Result.andThen Jsonl.parse
HTTP Permissions
[permissions.http]
enabled = true
allowed_hosts = ["api.example.com"]
| Field | Default | Description |
|---|---|---|
enabled | false | Enable HTTP requests |
allowed_hosts | — | Restrict requests to these hosts |
DataFrame Permissions
[permissions.dataframe]
enabled = true
sandbox = "./data"
max_rows = 1_000_000
| Field | Default | Description |
|---|---|---|
enabled | true | Enable DataFrame operations |
sandbox | — | Restrict DataFrame file access to this directory |
max_rows | — | Maximum number of rows allowed |
REPL
The [repl] section configures the interactive REPL (TUI and keel repl).
[repl]
undo_depth = 10
| Field | Default | Description |
|---|---|---|
undo_depth | 0 (disabled) | Number of undo steps to retain. Each step holds a full snapshot of the VM, including any loaded DataFrames. Set to 0 or omit to disable undo and avoid memory retention. |
Undo is disabled by default because each snapshot retains Arc references to every loaded DataFrame — a 5 GB DataFrame followed by 20 evals would keep 5 GB in the undo stack indefinitely. Enable it only when your data fits comfortably in memory.
Once enabled, use :undo or :u in the TUI or keel repl to step back through evaluations.
Running a Project
From anywhere inside a project directory:
keel run
This finds the nearest keel.toml by walking up from the current directory, applies permissions, and runs the entry point.
You can also run a specific file while still using the project's permissions:
keel run src/other.kl
Running without a manifest and without a file argument produces an error:
keel run
# Error: No file specified and no keel.toml found
Project Templates
Minimal (default)
The minimal template creates a simple project with just an entry point:
"Hello from my-project!"
Pipeline
The pipeline template scaffolds a data pipeline with extract/transform/load steps using tasks:
-- my-pipeline data pipeline
-- Run with: keel run
let { data } = run "steps/extract.kl"
let { transformed } = run "steps/transform.kl" { data }
run "steps/load.kl" { transformed }
Bare paths like "steps/extract.kl" resolve from the project root (the keel.toml directory). Inside the step files themselves, use ./ for paths relative to that file — see Path Resolution in the Tasks guide.
It also pre-configures IO and DataFrame permissions with a ./data sandbox.
Next Steps
- Modules — Organize code within files
- Error Handling — Handle errors in your pipelines