Development preview · Plutus V3

Cardano smart contracts,
written like Elm.

Elci is a pure, strongly typed functional language with Elm syntax. Your validators compile to compact Plutus V3 scripts through Julc, with strict data boundaries, multi-purpose validators and testing built in.

src/Main.elmvalidator main
module Main exposing (spend)

import Julc.Ledger exposing (PubKeyHash, ScriptContext)


{-| Accept only transactions signed by the owner.
-}
spend : PubKeyHash -> () -> () -> ScriptContext -> Bool
spend owner _ _ ctx =
    List.any
        (\signer -> signer == owner)
        ctx.txInfo.signatories
terminal
$ elci test my-contract
PASS MainTest.ownerSigns (cpu 7675163, mem 29990)
PASS MainTest.othersAreRejected (cpu 8053596, mem 31922)
2 passed, 0 failed
$ elci build my-contract
validator main (spend): checked; 300 FLAT bytes; plutus-v3-pv11-uplc-1.1.0
✓ strict datum decoding
✓ runs the deployed script

Why Elci

The clarity of Elm for code that moves value.

On-chain code has no second chance. Elci gives you a small, predictable functional language, and a compiler that refuses programs it cannot represent faithfully rather than erasing types to raw data.

Familiar and functional

Elm syntax, pure functions, currying and pipelines. If you have written Elm, Haskell or F#, you can read an Elci contract on day one.

Types that catch mistakes

Hindley–Milner inference, exhaustive pattern matching and rejected unreachable branches. Errors quote your code, name what differs and suggest a fix.

Strict data boundaries

Datums, redeemers and parameters are decoded strictly from their types. Malformed data fails before your logic runs.

One script, every purpose

Named validators combine spend, mint, withdraw, certify, vote and propose handlers, with deployment parameters and ABI drift checks.

Testing built in

Unit tests, transaction scenarios on the deployed script, and property tests that shrink failures, all written in Elci.

Standing on Julc

Julc's PIR verifier, optimizer and UPLC pipeline, its standard library, typed Map, Array and Bytes, and a fast native CLI.

See it in action

From validator to property test, in one language.

Real code from the Elci examples. Each sample compiles, and every test passes.

src/Vesting.elm
module Vesting exposing (VestingAction(..), VestingDatum, validate)

import Interval
import Julc.Ledger exposing (PubKeyHash, ScriptContext)
import Tx


type alias VestingDatum =
    { beneficiary : PubKeyHash
    , deadline : Int
    }


type VestingAction
    = Claim


validate : VestingDatum -> VestingAction -> ScriptContext -> Bool
validate datum action ctx =
    case action of
        Claim ->
            Interval.isEntirelyAfter datum.deadline ctx.txInfo.validRange
                && Tx.signedBy datum.beneficiary ctx

A typed datum and redeemer, the validity range and the signatories. The datum and redeemer are strictly decoded from their types before validate runs.

How it works

Your language, Julc's backend.

Elci owns the language: parsing, modules, type inference and lowering to typed PIR. Julc owns the rest: verification, linking, optimization and UPLC. The two meet at a checked, revisioned contract.

  1. 01.elm sourceModules, types and handlers
  2. 02Parse & resolveModules, imports, Java exports
  3. 03Infer & checkHM types, exhaustive patterns
  4. 04Typed PIRSpecialized, strict lowering
  5. 05Julc backendVerify, link, optimize
  6. 06Plutus V3UPLC script + ABI
build/validators/<name>/validator.plutus.jsonvalidator.plutusvalidator.flatabi.json

Learning path

From zero to a tested contract.

The documentation is one guided path. Start at the top, or jump to what you need.

Build with AI

Point your agent at Elci.

AI models have seen little Elci. A starter pack written for agents gives them the language, the APIs and the error fixes in one read, and elci check and elci test let them verify their own code. It works with Claude Code, Codex, Cursor, Copilot and any agent that can run a shell command.

prompt for your agent
You are writing Cardano smart contracts in Elci, an Elm-syntax language that compiles to Plutus V3.
Before writing any code, read https://elci-lang.dev/ai/starter-pack.md and follow it strictly.
After every change, run `elci check .` and `elci test .` and fix every ELCI error before continuing.

Quickstart

Three commands to a deployable script.

elci init creates a validator with a deployment parameter and two transaction scenarios. elci test runs them against the deployed script, and elci build writes Cardano-ready artifacts.

Install Elci
terminal
$ elci init my-contract
Created Elci project at my-contract with initial spend handler in validator main.
$ elci test my-contract
PASS MainTest.ownerSigns (cpu 7675163, mem 29990)
PASS MainTest.othersAreRejected (cpu 8053596, mem 31922)
2 passed, 0 failed
$ elci build my-contract
validator main (spend): checked; 300 FLAT bytes; plutus-v3-pv11-uplc-1.1.0

Ready to write your first contract?

Follow the guided path from installation to a tested, deployable validator.