Repository avatar
Other Tools
v0.7.1
active

lugh

io.github.Ashutosh3142857/lugh

Write, check and dry-run Lugh agent programs, with policy, budgets and approvals enforced.

Documentation

Lugh

CI Playground License: MIT

A programming language for AI agents that work through the infrastructure that already exists — APIs, websites, shells, files, SaaS apps and desktop software.

Lugh is named for the Irish god Samildánach, "skilled in all the arts". A Lugh program declares what an agent may touch, how much it may spend, and when a human must approve — and the runtime enforces all of it on every single action.

agent FlightScout
  use http, fs, shell, llm
  budget time 2m, calls 20
  policy
    allow read, write
    ask human before send, spend, submit
    deny delete

  goal "Find the cheapest Delhi to Dublin fare under 45000 INR"
    let fares = attempt
      http.get "https://api.flights.example/search?from=DEL&to=DUB" as json
    otherwise
      fs.read "examples/fares.json" as json

    let best = pick lowest price from fares
    ensure best.price < 45000 else stop "Nothing under budget"

    ask human "Book {best.airline} at INR {best.price}?" -> ok
    when ok
      send console "#travel" "Booking {best.airline}"

Try it

  • In your browser: the Lugh Playground runs Lugh compiled to WebAssembly, with nothing to install.
  • From a terminal, no install: npx lugh-lang run program.lugh runs a program in the same sandbox and prints a policy log (test, check and sandbox work too).
  • For AI agents, over MCP: npx lugh-lang mcp is an MCP server, listed in the MCP Registry as io.github.Ashutosh3142857/lugh. An agent can read the language reference, write a program, check it and dry-run it, then show you the policy log:
    { "mcpServers": { "lugh": { "command": "npx", "args": ["-y", "lugh-lang", "mcp"] } } }
    
  • Locally: lugh playground serves the same page on http://127.0.0.1:8000.
  • In VS Code: the extension adds highlighting, snippets, live error checking and run commands.

In the playground, adapters act on a simulated world: a few files, an HTTP API and four MCP servers (notes, GitHub, payments, mail), created fresh for every run. Nothing real is touched, but every call still passes the policy gate, so allow, ask and deny behave exactly as they do when installed, and each run ends with a policy log. Choose whether approvals are answered yes or no, share a program as a link, or run the same sandbox from a terminal or an agent with npx lugh-lang. Every run has a 10-second budget that also stops runaway computation.

Why a new language

Agent frameworks keep the things that matter most — permissions, spending limits, human approval, recovery from failure, an audit trail — outside the code, in config files and prompts. Lugh makes them syntax, so they are checked before a program runs and recorded while it runs.

ConcernIn Lugh
What the agent may dopolicy block, enforced by the runtime
Runaway cost or loopsbudget block: time, calls, spend
Human approvalask human is a built-in statement
Brittle integrationsattempt … otherwise fallback chains
Proof of what happenedEvery effect written to an audit log

Quick start

Python runtime: Python 3.9+, no dependencies. Native runtime: Rust 1.70+ to build.

git clone https://github.com/Ashutosh3142857/lugh-lang.git
cd lugh-lang

# Native runtime (Rust)
(cd core && cargo build --release)
./core/target/release/lugh examples/research_desk.lugh --yes --eval

# Reference runtime (Python)

python lugh.py examples/flight_scout.lugh --check   # list every action and its policy
python lugh.py examples/flight_scout.lugh           # run, approving actions as you go
python lugh.py examples/flight_scout.lugh --yes     # run with auto-approval

Optional:

  • pip install playwright && playwright install chromium enables the browser adapter.
  • Set ANTHROPIC_API_KEY so think uses a real LLM instead of the local stub (LUGH_MODEL selects the model).

What's new in v0.2

Primitives drawn from the foundational ML literature (details):

let urgent   = attend to inbox by "invoice overdue" top 2      # attention
let deadline = point to "payment due by date" in mail.body      # grounded extraction
remember "deadline" = deadline keep 7d                          # gated memory
let found    = recall like "northwind deadline"                 # content-addressed memory
let matched  = pairs i from invoices, p from payments where i.amount == p.amount
let fare     = consensus                                        # ensemble agreement
  pick lowest price from fs.read "a.json" as json
  pick lowest price from fs.read "b.json" as json
let quote    = attempt auto                                     # learned route order
  http.get "https://api.example.com/quote" as json
  fs.read "cache.json" as json
refine note with think "Improve this" with fare until count note > 20 rounds 2
let plan     = simplest of plans                                # minimum description length
let fresh    = novelty fare                                     # compression novelty
each m in matched parallel 4                                    # pipelined loop

Run the full demo:

python lugh.py examples/research_desk.lugh --yes --eval

Agents that write their own programs

lugh plan "Add a passport photos reminder and list my visa notes" --use mcp --run

An LLM writes the Lugh program, the compiler checks it (sending any error back for the model to fix), and you see the program and a report of everything it can touch before it runs. Generated programs run under plan safety: only reads happen without asking you, and deletes are always blocked.

Lugh connects to any MCP server (GitHub, Slack, Drive, Notion and thousands more) with the same config format as Claude Desktop. Each tool's effect comes from its MCP annotations, and policy decides before the call is sent. See MCP and plan.

use mcp
policy
  allow read
  ask human before submit
  deny delete
...
mcp.call "notes" "add_note" {title: "Biometrics"}   # asks you first
mcp.call "notes" "delete_note" {title: "x"}         # blocked by policy, never sent

Standard library

Lugh Core ships with what most projects pull in from the Python and JavaScript ecosystems: strings and regex, collections, maths and statistics, dates, JSON and CSV, hashing and UUIDs, schema validation, templates, SQLite, a test runner, scheduled jobs and token auth. See the standard library reference.

let cheap  = filter f in fares where f.price < 44000
let ranked = sort cheap by price
let errors = schema.check(request.body, {title: "text 2..80", amount: "number 0.01..1000000"})
db.exec "INSERT INTO expenses VALUES (?, ?, ?)" [uuid(), e.title, e.amount]
let report = csv.text(db.query "SELECT * FROM expenses")

test "only cheap fares"
  expect count(cheap) == 3
./core/target/release/lugh examples/stdlib_test.lugh --test   # 13 passed, 0 failed

examples/ledger.lugh puts it together: an expense tracker with a database, validation, token auth, an hourly job, CSV export and a web UI, in about 50 lines.

Full-stack apps: routes, pages and a human in the loop

One .lugh file can be an API, a web UI and an approval workflow (example, reference):

route POST "/api/book"
  let b = request.body
  ensure b.price < 45000 else respond 422 "Over budget"
  ask human "Book {b.airline} at INR {b.price}?" -> ok   # waits in the web inbox
  when ok
    respond 201 b
  otherwise
    respond 403 "Rejected"

page "/" title "Fare desk"
  stat from "/api/best" field price label "Lowest fare (INR)"
  table from "/api/fares" columns airline, depart, price
  form to "/api/book" fields airline, price submit "Request booking"
./core/target/release/lugh examples/fare_desk.lugh --serve 8080
# open http://127.0.0.1:8080 and the approvals inbox at /_lugh/inbox

ask human inside a route pauses that request until someone clicks Approve or Reject in the inbox. Pages are server-rendered HTML (about 6 KB each, including styles and script) with no build step.

Two runtimes

Python reference (lugh.py)Lugh Core (core/, Rust)
Use it forPrototyping, the browser adapterProduction, scale, embedding
InstallPython 3.9+One 5.9 MB binary (SQLite included), libc only
Adaptershttp, fs, shell, browser, llmhttp, fs, shell, db, mcp, llm
Web (routes, pages, inbox, auth, jobs)—Yes
Standard library, test blocks, lugh planCore language onlyYes

Both runtimes produce identical results on the bundled examples.

Benchmarks

Measured with python bench/gen.py && python bench/run.py (Linux x86-64, mean of repeated runs; peak memory of the measured process alone):

WorkloadPythonLugh CoreSpeed-upMemory
Startup (bench/hello.lugh)79 ms, 22.3 MB2.9 ms, 4.8 MB27×4.6× less
1,000,000 relational comparisons + attention over 3,000 emails (bench/heavy.lugh)1,925 ms, 26.2 MB321 ms, 14.9 MB6.0×1.8× less

Numbers vary by machine. An agent's wall-clock time is usually dominated by network and model latency; Core's advantage is cheap startup, a small footprint and real parallelism when many agents run at once.

Effects and policy

Every action belongs to one of seven effect types. Policy is written against these, so reviewing an agent means understanding seven words rather than every API it calls.

EffectMeaningDefault when not listed
readObserves, changes nothingask human
writeChanges local or draft stateask human
submitCommits an action in another systemask human
sendReaches another personask human
spendMoves moneyask human
executeRuns code or commandsask human
deleteIrreversible removalask human

Anything not explicitly allowed requires approval, so a missing policy line makes an agent more cautious, never less. Policy denials and budget overruns cannot be caught by attempt, so an agent cannot route around its limits.

Adapters

AdapterReachesStatus
httpREST / JSON APIsWorking
fsLocal filesWorking
shellInstalled CLI toolsWorking
browserAny website (Playwright)Working
llmReasoning via think (with samples N)Working
mcpSaaS apps via Model Context ProtocolPlanned (v0.3)
appDesktop software via OS accessibility APIsPlanned (v0.5)

An adapter is one class: a map of verb → effect and a call(verb, args) method.

Documentation

Roadmap

  1. Learn (v0.2) ✓ — research-derived primitives, adaptive routing, evaluation
  2. Native (v0.3) ✓ — Lugh Core: Rust runtime, compile-once execution, benchmarks
  3. Full stack (v0.4) ✓ — routes, pages, approvals inbox, end-to-end tests
  4. Standard library (v0.5) ✓ — 100+ functions, SQLite, tests, jobs, auth, object literals
  5. Connect (v0.6) ✓ — MCP client, lugh plan with self-repair and plan safety
  6. Reach (v0.7) ✓ — browser playground (WebAssembly), VS Code extension, multi-line lists and objects, CI
  7. Compile (v0.8) — bytecode VM, field access compiled to fixed slots
  8. Ecosystem (v0.9) — package manager, language server, multi-agent message passing
  9. Desktop (v0.10) — desktop app adapter, screen fallback, spend metering
  10. Trust (v1.0) — TLS, user accounts and roles for served apps, signed audit logs, shareable policy packs, automatic fallback ladder
  11. Platform — hosted runtime, adapter marketplace, team approvals

Support Lugh

Lugh is free and open source. If it's useful to you, you can support its development:

NetworkAddress
Bitcoinbc1q3w9542hnh4qykqnfsjg9dcq49fhm8dtuwtydhy
Ethereum0x15b4939bcf8c8FA80c320566c4d9D49c9078e1C2

Please send each coin only on its own network.

Contributions of code, examples, adapters and bug reports are just as welcome.

License

MIT © 2026 Ashutosh Pandey

NPM
lugh-lang
Install Command
npm install lugh-lang