-
Notifications
You must be signed in to change notification settings - Fork 0
Language Tutorial
Learn Kyto from basics to a full compile pipeline.
Beginner tip: Start with Getting Started and
config_only = true. Come back here when you need custom logic in.kytofiles.
Most projects only need .kyto.config + kura compile. No .kyto files required.
See Configuration Guide for every directive.
Create kyto/main.kyto:
+ Minimal Kyto program
emit env({
"APP_URL": "https://demo.local",
"NODE_ENV": "development",
})
Set in kyto.toml:
[project]
config_only = false
entry = "kyto/main.kyto"Run kura compile. The emit env(...) call writes your .env file.
+ This is a comment (plus at line start)
let x = 1 + inline comments also work after code on same line in some contexts
In .kyto.config, + comments run to end of line.
enum Role {
Admin
User
}
struct User {
name: string
role: Role
}
let users: User[] = []
Structs and enums define the shape of data you emit.
fn build_env(secrets) -> map<string, string> {
return {
"APP_URL": "https://" + secrets.domain,
"SESSION_SECRET": secrets.session_secret,
}
}
Functions return values used by emit calls.
Split logic across files:
import local from "./local.kyto"
kyto/local.kyto can hold secrets structs:
struct Secrets {
domain: string
session_secret: string
}
let secrets = Secrets {
domain: "demo.local",
session_secret: "",
}
Kyto programs do not print to stdout. They emit artifacts:
| Statement | Output |
|---|---|
emit env(map<string,string>) |
.env + .env.example
|
emit users(list<User>) |
SQL, JSON, TypeScript user lists |
emit deploy(map<string,string>) |
Bash export script |
Full program example (from examples/minimal):
import local from "./local.kyto"
enum Role { Admin User }
struct User {
name: string
role: Role
}
let users: User[] = []
fn build_env(secrets) -> map<string, string> {
let secret = secrets.session_secret
if secret == "" {
secret = random_base64(32)
}
return {
"APP_URL": "https://" + secrets.domain,
"SESSION_SECRET": secret,
"NODE_ENV": "development",
}
}
let deploy = { repo_dir: "." }
emit env(build_env(local.secrets))
emit users(users)
emit deploy(deploy)
| Function | Description |
|---|---|
random_base64(n) |
Cryptographically useful random string (length n) |
len(x) |
Length of string, list, or map |
require(cond, msg) |
Stop compile with error if condition is false |
Example:
require(len(secrets.domain) > 0, "domain must not be empty")
if secret == "" {
secret = random_base64(32)
} else {
+ keep existing
}
for user in users {
+ loop body (evaluator support evolving)
}
let fn struct enum import
if else for in return
emit true false
Full grammar: https://github.com/voidmute/kyto/blob/main/spec/grammar.md
The power move: .kyto.config for daily edits, .kyto for logic.
- Users and domain live in
.kyto.config(ops-friendly) -
kyto/main.kytomerges them into env maps and deploy scripts -
kura compileproduces everything
Set config_only = false in kyto.toml when using both layers.
kura check # parse + evaluate, no file writes
kura compile # write all artifactsUse kura check in CI before deploy.
| Mistake | Fix |
|---|---|
Empty .env after compile |
Set config_only correctly; ensure .kyto.config exists |
| Users not in SQL output | Define USERS in .kyto.config or populate users in .kyto
|
| Secrets in git | Gitignore .env and .kyto.config; commit .env.example only |
kura: command not found |
Run kura install or add bin/ to PATH |
-
Configuration Guide — every
kyto.tomlkey -
Encryption & Privacy — protect
local.kyto - Architecture — how the evaluator works inside kura