v0.15 state: type-directed lowering throughout, Go generics on parametric record aliases. Layer-3 stdlib, whole-program DCE (Stripe-SDK scale: −82 % source), LSP 100 % coverage; runtime verification across all 27 examples (120 stdlib assertions + 306 cabal specs). See
../compiler/versions.mdfor the changelog.
Every sky subcommand. Run sky --help for the authoritative list.
Compile a Sky source file to a Go binary under sky-out/.
sky build src/Main.skyPipeline:
- Parse
sky.tomlfor[go.dependencies]and[dependencies]. - Auto-regenerate any missing FFI bindings in
.skycache/. - Resolve modules, type-check, lower to Go under
sky-out/. - Invoke
go build→sky-out/app(or thebinname set insky.toml).
sky build + execute the resulting binary.
Fully validate the program. sky check is a strict superset of sky build:
it runs parsing, canonicalisation, HM inference, Go codegen, and invokes
go build on the emitted output — without producing a runnable binary. If
sky build would fail, sky check fails with the same error. This is the
soundness gate — editor integrations should use it directly.
File-watch-driven hot rebuild + restart. Watched scope is a strict
allowlist: sky.toml + the entry-point's directory (recursive .sky
walk) + tests/ at the project root if present. Generated dirs
(sky-out/, .skycache/, .skydeps/, node_modules/, .git/) are
excluded.
sky watch # entry: src/Main.sky
sky watch src/Main.sky # explicit entry
sky watch --no-run # rebuild only (don't spawn)
sky watch --clear # clear screen between rebuilds
sky watch --interval=200 # poll interval ms (default 200)
sky watch --debounce=150 # debounce after a change (default 150)
sky watch --kill-timeout=3000 # SIGTERM grace before SIGKILL
sky watch --watch=docs/notes.md # additional path (repeatable)Build-error policy: on a failing rebuild, the previously-running binary stays alive. The next successful build kills + respawns. A typo halfway through a save doesn't tear down the dev session.
Caches reused: .skycache/source.hash (full short-circuit on
unchanged source), .skycache/lowered/ (per-module IR),
.skycache/ffi/*.skyi (HM types — never regenerated by watch).
Typical warm rebuild: 1-3 s.
Signals: Ctrl-C and SIGTERM both go through the clean-teardown path. Sky.Live's SSE handshake auto-reconnects post-restart (banner shows "Reconnecting…" for ~1 s then clears).
Browsable API documentation for the Sky stdlib + project + deps. Four modes:
sky doc Sky.Core.String # terminal: list every symbol with its HM signature
sky doc List # shorthand for Sky.Core.List
sky doc --list # print every documented module
sky doc --serve # HTTP doc server (auto-opens browser)
sky doc --serve --port 8081 # custom port
sky doc --tui # interactive terminal doc browser (Sky.Tui)--serve and --tui are mutually exclusive — --serve runs the
Sky.Http.Server bundle; --tui runs the Sky.Tui bundle. Both
consume the same on-disk catalogue rendered to .skycache/doc-out/
under the project root.
The HTTP server (default :8080) renders:
- Per-module pages with HM signatures, Markdown-rendered doc
comments, and an in-module symbol filter (counter shows
X / Y). - Fuzzy search by name, module, OR type signature
(Hoogle-style, case-insensitive —
string -> intorString -> Intboth findString.length,String.toIntetc.). - FFI binding browsing — every imported Go-pkg FFI dep lists its surface alongside the stdlib.
- Live reload if the underlying project changes (re-runs the index build on each request).
The server is a Sky.Live mini-app bundled into the compiler binary
(sky-bundled/doc/), spawned as a child + reverse-proxied behind
the sky doc --serve entry point.
--tui runs the Sky.Tui sibling (sky-bundled/doc/src/MainTui.sky)
which reads the same JSON catalogue and renders an interactive
terminal view: ↑/↓ navigate, Enter expands the highlighted entry,
/ focuses the search box, Esc clears, Ctrl-C quits.
Project + environment health checks. v0.15.48 shipped 15 checks
total — the foundational 5 (sky.toml syntax, stale .skycache/,
stale sky-out/, port-in-use, missing FFI) plus 10 tooling-polish
additions:
| Check id | Severity | What it covers |
|---|---|---|
go-toolchain |
error | Go ≥ 1.22 on PATH |
ffi-cache-orphan |
warn | .skycache/ffi/*.skyi with no .skydeps/ source |
missing-lockfile |
info | .skydeps/ populated but no sky.lock |
auth-secret-short / auth-secret-missing |
error / warn | SKY_AUTH_TOKEN_SECRET ≥ 32 bytes when [live] / [auth] set |
ci-parity |
info | .github/workflows/ci.yml invokes sky build / cabal test / verify-*.sh |
stdlib-version-drift |
warn (fixable) | .skycache generated by a different Sky compiler version |
toml-unknown-section |
info | sky.toml top-level keys outside the known set |
subapp-bin-missing |
warn | [subapp] bin = "..." paths are executable |
check-smoke |
info | reminder to run sky check when build is current |
govulncheck-* |
info | flags govulncheck availability for Go-runtime CVE scanning |
The Sky compiler repo also gets mem-guard (Info: running
mem-guard.sh check) — gated to the compiler repo so user projects
don't see it.
sky doctor # report only
sky doctor --fix # apply safe fixes (clean stale caches, etc.)
sky doctor --verbose # print check-id alongside each findingExit codes: 0 clean, 1 warnings, 2 errors. CI-friendly.
CI canonical runtime check. Iterates every directory under examples/
(or the named one), builds, runs, and asserts runtime behaviour:
- HTTP examples: hits
/(and any routes declared inexamples/<n>/verify.json) and checks status codes + body substrings. - GUI examples (Fyne): skipped on headless CI via
SKY_SKIP_GUI=1.
Output lines: runtime ok: <name>, FAIL scenario: ..., FAIL build: ...,
[skip] <name>: .... Exit code is non-zero if any example fails.
Scenario file format:
{
"requests": [
{ "method": "GET", "path": "/", "expectStatus": 200, "expectBody": ["Hello"] },
{ "method": "GET", "path": "/api/status", "expectStatus": 200, "expectBody": ["status"] }
]
}Run a Sky test module. See testing.md.
Inspect and apply Std.Db schema migrations. FILE defaults to
src/Main.sky.
sky db status # report applied / pending / drifted migrations, then exit
sky db migrate # apply all pending migrations in order, then exitBoth build the project, then run it in DB-ops mode — the app's
Db.migrate call does the work and exits before serving. The
underlying mechanism is the SKY_DB_OP env var (status / migrate),
usable directly in a deploy pipeline: SKY_DB_OP=migrate ./sky-out/app.
sky db statusexits non-zero on drift (an applied migration whose SQL was edited) — use it as a CI schema-drift gate.sky db migrateexits non-zero if a migration fails — run it as a pre-cutover deploy step so a bad migration blocks the rollout.- There is no
migrate <singlefile>: migrations are an ordered, checksum-tracked set;migratealways applies every pending one.
See Sky.Db — Schema migrations.
Removes:
sky-out/— compiled binary + Go source.skycache/— generated FFI bindings, lowered-module cache, incremental state.skydeps/— Sky source dependencies (if any)dist/— release archives
Rebuild from scratch with sky build after sky clean.
Fetches a Go module, runs the FFI inspector, generates .skycache/ffi/<slug>.{skyi,kernel.json} + .skycache/go/<slug>_bindings.go. Records the dependency in sky.toml under [go.dependencies].
sky add github.com/google/uuid
sky add github.com/stripe/stripe-go/v84The FFI inspector (sky-ffi-inspect) is embedded in the sky
binary and self-provisions into $XDG_CACHE_HOME/sky/tools/ on
first use — no separate install required. Cold start costs one
go build (~4s); subsequent calls are instant. Content-hashed
cache means sky upgrade invalidates the helper automatically.
Overrides, in probe order:
$SKY_FFI_INSPECTOR— absolute path to a pre-built helper.bin/sky-ffi-inspectin the cwd or any ancestor (dev workflow).- Embedded fallback (default for installed binaries).
Drops the dependency from sky.toml and prunes the Go module cache.
Re-fetches every declared dependency. Idempotent — skips packages whose bindings are already present.
Bumps all [go.dependencies] to their latest versions.
Self-upgrades the sky binary from the latest GitHub release.
Refreshes the cwd's CLAUDE.md from the template embedded in the
running sky binary at build time. Useful after sky upgrade —
the binary's embedded template moves with new releases (new stdlib
APIs, deprecation notes, current limitations) but a project's
CLAUDE.md is a snapshot taken at sky init time and won't auto-
update.
Behaviour:
- Always overwrites
./CLAUDE.md(the file is AI-context, not hand-edited project source). - Backs the prior file up to
./CLAUDE.md.bakso an accidental run on a project that customised the file is recoverable. - Prints a one-line summary including the byte-count delta and the
skyversion that produced the new template, so you can see at a glance whether the template actually changed.
$ sky upgrade-claude
Refreshed CLAUDE.md (118432 → 132422 bytes, from sky v0.11.1)
previous version saved as CLAUDE.md.bakRuns the bundled Sky Console mini-app standalone. The console is
also auto-mounted at /_sky/console inside every Sky.Live and
Sky.Http.Server app in dev mode — the standalone form is for
ad-hoc inspection when you don't have (or don't want to start)
a host app.
sky console # Sky.Live in the browser on :8025
sky console --port 8030 # different port
sky console --tui # same UI rendered through Sky.Tui in your terminalThe source lives in sky-bundled/console/ (embedded into the sky
binary via Template Haskell). First invocation builds into
$XDG_CACHE_HOME/sky/console-<version>/ (~3–10 s); subsequent
runs are instant. Cache keys include the version string so
sky upgrade auto-invalidates.
Live and TUI variants share the same State.sky + View.sky —
only the entry-point module switches between Live.app and
Tui.app. Cached binaries are kept side-by-side (app-live /
app-tui) so switching backends doesn't trigger a rebuild.
Env flags (full reference in CLAUDE.md):
SKY_CONSOLE_EMBED=off— opt-out of the auto-mount inside user apps (the standalone CLI still works).SKY_DEV_BANNER=off— opt-out of the floating "🔍 Console" banner without disabling the mount.SKY_CONSOLE_URL=https://...— override the banner's href (e.g. to point at a remote shared dashboard).ENV=production(orSKY_ENV=…outside{dev, development, local}) — production-mode gate; suppresses console + banner entirely and gates/_sky/metricsbehind auth.
Opinionated, deterministic, no configuration (output is Elm-compatible):
- 4-space indent, no tabs.
- Leading commas for multi-line lists/records.
- Pipelines broken onto new lines.
- Refuses to overwrite if the formatter would lose more than one-third of the source lines (guards against partial-parse deletions).
Starts the Language Server over JSON-RPC / stdio. Used by the Helix and Zed integrations and any LSP-aware editor.
See lsp.md for configuration snippets.
Sky writes generated artefacts to predictable locations — everything under .skycache/ and sky-out/ is regenerable. Nothing generated lives alongside your source.
project/
src/ -- your Sky source
sky.toml -- manifest
.skycache/
ffi/ -- .skyi signatures + kernel.json registries
go/ -- generated Go FFI wrappers
lowered/ -- incremental lowered-module cache
.skydeps/ -- Sky source deps (if any)
sky-out/ -- compiled binary + lowered main.go + rt/