sky-lang.org · Examples · Docs
Experimental · v0.10 — Sky is under active development. APIs and internals may change between minor versions.
Sky is an experimental fullstack programming language that combines Go's pragmatism with Elm's elegance. You write functional, strongly-typed code with a batteries-included stdlib — Sky.Live for server-driven UI, Std.Db for SQL persistence, Std.Auth for sessions, Sky.Core.Error for unified error handling — import any Go package with auto-generated FFI bindings (no hand-written glue), and ship a single portable binary. Sky's explicit types, exhaustive pattern matching, and strict Task effect boundary make it AI-friendly by design: both humans and LLMs tend to write code that compiles the first time.
module Main exposing (main)
import Std.Log exposing (println)
main =
println "Hello from Sky!"- Go — fast compilation, single static binary, access to the full Go ecosystem (databases, HTTP servers, cloud SDKs).
- Elm — Hindley-Milner type inference, algebraic data types, exhaustive pattern matching, pure functions, The Elm Architecture.
- Phoenix LiveView — server-driven UI with DOM diffing, SSE subscriptions, session management. No client-side framework required.
Sky compiles to Go. One binary runs your API, DB access, and server-rendered interactive UI — one codebase, one language, one deployment artifact.
I've worked professionally with Go, Elm, TypeScript, Python, Dart, Java, and others for years. Each has strengths, but none gave me everything I wanted: simplicity, strong guarantees, functional programming, fullstack capability, and portability — all in one language.
The pain point that kept coming back: startups and scale-ups building React/TypeScript frontends talking to a separate backend, creating friction at every boundary — different type systems, duplicated models, complex build pipelines, and the constant uncertainty of "does this actually work?" that comes with the JS ecosystem. Maintenance becomes the real cost, not the initial build.
I always wanted to combine Go's tooling (fast builds, single binary, real concurrency, massive ecosystem) with Elm's developer experience (if it compiles, it works; refactoring is fearless; the architecture scales). Then, inspired by Phoenix LiveView, I saw how a server-driven UI could eliminate the frontend/backend split entirely — one language, one model, one deployment.
The first attempt compiled Sky to JavaScript with the React ecosystem as the runtime. It worked, but Sky would have inherited all the problems I was trying to escape — npm dependency chaos, bundle configuration, and the fundamental uncertainty of a dynamically-typed runtime. So I started over with Go as the compilation target: Elm's syntax and type system on the frontend, Go's ecosystem and binary output on the backend, with auto-generated FFI bindings that let you import any Go package and use it with full type safety.
Building a programming language is typically a years-long effort. What made Sky possible in weeks was AI-assisted development — first with Gemini CLI, then settling on Claude Code, which fits my workflow and let me iterate on the compiler architecture rapidly. I designed the language semantics, the pipeline, the FFI strategy, and the Live architecture; AI tooling helped me execute at a pace that would have been impossible alone.
Sky is named for having no limits. It's experimental, opinionated, and built for one developer's ideal workflow — but if it resonates with yours, I'd love to hear about it.
The compiler is written in Haskell (GHC 9.4+). It handles parsing, Hindley-Milner type inference, canonicalisation, formatting, LSP, and Go codegen. Previous implementations (TypeScript bootstrap, Go, self-hosted Sky) are preserved under legacy-ts-compiler/ and legacy-sky-compiler/ for historical reference.
See docs/compiler/journey.md for the full compiler history.
Sky is batteries-included. Three killer modules cover the common needs of any modern web app — no plugins, no separate services, no npm install:
The Elm Architecture, but the server is authoritative. No client framework, no JSON API contracts, no bundler. Browser runs ~2 KB of JS for DOM diffing + SSE — that's it.
type Msg = Increment | Decrement
update msg model =
case msg of
Increment -> ( { model | count = model.count + 1 }, Cmd.none )
Decrement -> ( { model | count = model.count - 1 }, Cmd.none )
view model =
div []
[ button [ onClick Increment ] [ text "+" ]
, span [] [ text (String.fromInt model.count) ]
, button [ onClick Decrement ] [ text "-" ]
]Full TEA loop with init / update / view / subscriptions, async work via Cmd.perform, persistent sessions across deploys (memory / SQLite / Redis / Postgres / Firestore). See Sky.Live overview.
bcrypt password hashing, HMAC-SHA256 JWTs, plus optional DB-backed register / login that creates the users table for you. No passport, no bcryptjs, no auth microservice.
Auth.register db "alice@example.com" password
|> Task.andThenResult
(\uid ->
Auth.signToken secret (Dict.fromList [ ( "sub", String.fromInt uid ) ]) 86400
)Production-grade defaults: minimum-32-byte secret enforcement, constant-time password compare, configurable bcrypt cost, rate-limit-friendly. See Sky.Auth overview.
Parameter-safe queries, transactions, conventional CRUD helpers (insertRow / getById / updateById / deleteById), row decoders. Switch driver in sky.toml; never touch it again in your code.
Db.withTransaction db (\tx ->
Db.exec tx "UPDATE accounts SET balance = balance - ? WHERE id = ?" [ amount, fromId ]
|> Task.andThen (\_ ->
Db.exec tx "UPDATE accounts SET balance = balance + ? WHERE id = ?" [ amount, toId ]
)
)See Std.Db overview.
Crypto, JSON, HTTP client/server, file I/O, time, regex, encoding (base64 / hex / URL), structured logging, UUIDs, async tasks, parallel execution. See Standard library reference for the full surface.
# macOS / Linux — single-binary install
curl -fsSL https://raw.githubusercontent.com/anzellai/sky/main/install.sh | sh
# custom installation path
curl -fsSL https://raw.githubusercontent.com/anzellai/sky/main/install.sh | sh -s -- --dir ~/.local/bin
# Or with Docker
docker run --rm -v $(pwd):/app -w /app anzel/sky sky --helpPrerequisite: Go 1.21+ installed — Sky compiles to Go and uses Go's toolchain to produce your binary.
Create and run a project:
sky init hello
cd hello
sky run src/Main.skySky ships as a single sky executable. The FFI-introspection
helper (sky-ffi-inspect) is embedded and self-provisions into
$XDG_CACHE_HOME/sky/tools/ on first sky add — no second binary
to install or keep on $PATH.
See docs/getting-started.md for a walkthrough.
Contributors: see docs/development.md for the
full build + test story, including the pinned GHC/Go toolchain, the
./scripts/build.sh entrypoint, and reproducible builds via Nix:
# quickest path on any system with nix
nix develop # GHC 9.4.8 + Go + every system dep, sandboxed
./scripts/build.sh --clean| Area | Link |
|---|---|
| Getting started | docs/getting-started.md |
| Language syntax | docs/language/syntax.md |
| Types | docs/language/types.md |
| Pattern matching | docs/language/pattern-matching.md |
| Modules | docs/language/modules.md |
| Go FFI interop | docs/ffi/go-interop.md |
| FFI design | docs/ffi/ffi-design.md |
| Error system | docs/errors/error-system.md |
| Standard library reference | docs/stdlib.md |
| Sky.Auth overview | docs/skyauth/overview.md |
| Std.Db overview | docs/skydb/overview.md |
| Sky.Live overview | docs/skylive/overview.md |
| Sky.Live architecture | docs/skylive/architecture.md |
| Compiler architecture | docs/compiler/architecture.md |
| Compiler pipeline | docs/compiler/pipeline.md |
| Compiler journey (TS→Go→Sky→Haskell) | docs/compiler/journey.md |
| Version history | docs/compiler/versions.md |
| CLI reference | docs/tooling/cli.md |
Testing (sky test) |
docs/tooling/testing.md |
| LSP | docs/tooling/lsp.md |
| Development & contributing | docs/development.md |
- v0.10 — stdlib consolidation + soundness gaps closed (2026-04-25, BREAKING). Single canonical module per concern (drop
Args/Env/Sha256/Hex/Slog; renameOs→System; shrinkProcesstorun); type errors in dep modules and FFI / kernel return shapes now abort the build instead of silently degrading toany-typing. See docs/V0.10.0_PR_SUMMARY.md for the full migration guide. - v0.9 — adversarial audit remediation complete (2026-04-16). All 23 P0–P3 items across soundness, security, cleanup, and tooling landed with regression tests. See docs/AUDIT_REMEDIATION.md for the per-item tracker and docs/compiler/v1-soundness-audit.md for the soundness audit findings.
- Core principle — "if it compiles, it works" — aspirational. Now holds for every path in
cabal test, the example sweep, and the runtime Go test matrix. v1.0 requires production usage and bug-fixes to earn the label. Residual future-work (fully-typed emitted Go, Sky-test harness) tracked in docs/PRODUCTION_READINESS.md as P4. - 18 example projects under
examples/covering CLI, HTTP servers, full-stack Sky.Live apps, databases (SQLite, PostgreSQL, Firestore), payments (Stripe), auth, and GUI (Fyne). sky verifyis the canonical runtime check: builds and runs every example, hits HTTP endpoints, honours per-exampleverify.jsonscenarios (status code + body substring assertions). CI runssky verifyacross the full example set.- Test matrix: 47-example hspec suite + ~20 runtime Go tests + 67-file
test-files/*.skyself-test loop + format idempotency across every example source file. - FFI generation: Stripe SDK (8,896 types), Firestore, Fyne, and others auto-bind.
Issues and PRs welcome. See the docs tree for architecture context before opening a structural PR.
MIT.