{"id":43383410,"url":"https://github.com/rcrsr/rill","last_synced_at":"2026-05-01T02:01:36.203Z","repository":{"id":333812463,"uuid":"1138587136","full_name":"rcrsr/rill","owner":"rcrsr","description":"Embeddable workflow language for LLM orchestration","archived":false,"fork":false,"pushed_at":"2026-03-07T03:47:25.000Z","size":8240,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-07T12:33:18.226Z","etag":null,"topics":["ai-agents","dsl","embeddable","interpreter","llm","parser","pipe","scripting-language","typescript","workflow"],"latest_commit_sha":null,"homepage":"https://rill.run","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rcrsr.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-20T21:35:25.000Z","updated_at":"2026-03-07T05:20:36.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rcrsr/rill","commit_stats":null,"previous_names":["rcrsr/rill"],"tags_count":115,"template":false,"template_full_name":null,"purl":"pkg:github/rcrsr/rill","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rcrsr%2Frill","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rcrsr%2Frill/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rcrsr%2Frill/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rcrsr%2Frill/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rcrsr","download_url":"https://codeload.github.com/rcrsr/rill/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rcrsr%2Frill/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30246626,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T00:58:18.660Z","status":"online","status_checked_at":"2026-03-08T02:00:06.215Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","dsl","embeddable","interpreter","llm","parser","pipe","scripting-language","typescript","workflow"],"created_at":"2026-02-02T09:24:33.196Z","updated_at":"2026-05-01T02:01:36.189Z","avatar_url":"https://github.com/rcrsr.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/rill.png\" alt=\"rill logo\" width=\"280\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/rcrsr/rill/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/rcrsr/rill/actions/workflows/ci.yml/badge.svg?branch=main\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@rcrsr/rill\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@rcrsr/rill\" alt=\"npm\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@rcrsr/rill\"\u003e\u003cimg src=\"https://img.shields.io/node/v/@rcrsr/rill\" alt=\"Node\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/rcrsr/rill/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/npm/l/@rcrsr/rill\" alt=\"License\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n**[rill](https://rill.run)**: *Scripting designed for machine-generated code*\n\n\u003e [!WARNING]\n\u003e **This language is experimental.** While usable, there may still be some warts and bugs. Breaking changes will occur before stabilization.\n\n## The Problem\n\nGeneral-purpose languages weren't designed for machine authorship. They allow null, exceptions, implicit coercion, and ambiguous syntax — and no amount of prompting can structurally prevent an LLM from generating them.\n\nrill makes these failure categories impossible at the language level. No null, no exceptions, no implicit coercion. Variables lock type on first assignment. The `$` prefix enables single-pass parsing without a symbol table. Errors halt — control flow is singular and explicit.\n\nThe host application controls what capabilities are available. No filesystem, no network, no side effects unless explicitly provided. Zero dependencies. Embeds in Node, Bun, Deno, or the browser.\n\n## What This Looks Like\n\nDefensive code you write because the language allows it:\n\n```python\nasync def classify_and_route(task: str) -\u003e dict:\n    # Call LLM — might throw, might return None\n    try:\n        response = await llm.classify(task)\n    except Exception as e:\n        return {\"error\": f\"Classification failed: {e}\"}\n\n    # Response might be None, might be wrong type\n    if response is None:\n        return {\"error\": \"No response from classifier\"}\n\n    if not isinstance(response.category, str):\n        return {\"error\": f\"Expected string, got {type(response.category)}\"}\n\n    # Route based on category\n    handlers = {\n        \"billing\": handle_billing,\n        \"technical\": handle_technical,\n        \"general\": handle_general,\n    }\n\n    handler = handlers.get(response.category, handle_general)\n\n    try:\n        result = await handler(task)\n    except Exception as e:\n        return {\"error\": f\"Handler failed: {e}\"}\n\n    if result is None:\n        return {\"error\": \"Handler returned None\"}\n\n    return result\n```\n\nWhat's left when the failure modes are structurally impossible:\n\n```rill\n# No null. No exceptions. No wrong types. If it parses, it's safe to run.\n\nuse\u003cext:app\u003e =\u003e $app\n\n$task\n  -\u003e $app.classify\n  -\u003e .category:string\n  -\u003e [\n    billing:   $app.handle_billing,\n    technical: $app.handle_technical,\n    general:   $app.handle_general\n  ] ?? $app.handle_general\n  -\u003e $($task)\n```\n\nEvery defensive check in the Python maps to a failure category rill eliminates:\n\n| Python defensive code | Why it doesn't exist in rill |\n|-----------------------|------------------------------|\n| `try/except` around LLM call | No exceptions. Errors halt. |\n| `if response is None` | No null. Functions always return. |\n| `isinstance()` type check | `:string` asserts type inline or halts. |\n| `try/except` around handler | No exceptions. Errors halt. |\n| `if result is None` | No null. Functions always return. |\n\n## Why rill?\n\nFour tenets drive every design decision:\n\n| Tenet | Trade-off |\n|-------|-----------|\n| **Structural Safety over Familiarity** | No null, no exceptions, no implicit coercion. If it parses, it's safe to run. |\n| **LLM Authorship over Human Ergonomics** | `$` prefix, type locking, explicit booleans. Syntax optimizes for unambiguous codegen. |\n| **Host Authority over Ambient Capability** | Scripts start with zero capabilities. The host grants exactly what it intends. |\n| **Halt over Recover** | No try/catch. Scripts return a complete result or an error, never partial state. |\n\nShips with [EBNF grammar](docs/ref-grammar.ebnf) and [LLM reference](docs/ref-llms-full.txt) (with [index](docs/ref-llms.txt) and [progressive fragments](docs/llm/)). Zero dependencies. [Embeds](docs/integration-host.md) in Node, Bun, Deno, or the browser.\n\n## Who Is This For?\n\n**Developers building AI agents, copilots, and automation tools** who need a scripting runtime that LLMs can generate code for and end users can execute without risk.\n\nrill is not a general-purpose language — it's intentionally constrained. For general application development, use TypeScript, Python, or Go.\n\nrill powers [Claude Code Runner](https://github.com/rcrsr/claude-code-runner), a rich automation tool for Claude Code.\n\n## Quick Start\n\n```typescript\nimport { parse, execute, createRuntimeContext, extResolver } from '@rcrsr/rill';\nimport { createOpenAIExtension } from '@rcrsr/rill-ext-openai';\n\nconst ext = createOpenAIExtension({\n  api_key: process.env.OPENAI_API_KEY,\n  model: 'gpt-4o',\n});\n\nconst ctx = createRuntimeContext({\n  resolvers: { ext: extResolver },\n  configurations: {\n    resolvers: {\n      ext: { llm: ext.value },\n    },\n  },\n});\n\nconst result = await execute(parse(`\n  use\u003cext:llm\u003e =\u003e $llm\n  $llm.message(\"Summarize this code for issues\")\n    -\u003e .content -\u003e .contains(\"ERROR\") ? \"Issues found\" ! \"All clear\"\n`), ctx);\n\nawait ext.dispose?.();\n```\n\nSwitch providers by changing one line — `createAnthropicExtension` or `createGeminiExtension`. Scripts stay identical.\n\n## Extensions\n\nCore extensions ship with `@rcrsr/rill`: fs, fetch, exec, kv, crypto. Vendor extensions (LLM providers, vector databases, storage backends, MCP) live in [rill-ext](https://github.com/rcrsr/rill-ext).\n\nSee [Bundled Extensions](docs/bundled-extensions.md) for core extension docs and [Developing Extensions](docs/integration-extensions.md) to write your own.\n\n## Related Repositories\n\n| Repository | Description |\n|------------|-------------|\n| [rill-ext](https://github.com/rcrsr/rill-ext) | Vendor extensions — LLM providers, vector databases, storage backends, MCP |\n| [rill-agent](https://github.com/rcrsr/rill-agent) | Agent framework — harness, bundle, proxy, build, run CLIs |\n| [rill-cli](https://github.com/rcrsr/rill-cli) | CLI tools — rill-exec, rill-eval, rill-check, rill-run |\n| [rill-config](https://github.com/rcrsr/rill-config) | Config library — project resolution, extension mounting |\n\n## Language Overview\n\n### Pattern-Driven Conditionals\n\nBranch based on content patterns. Ideal for parsing LLM output.\n\n```rill\nuse\u003cext:app\u003e =\u003e $app\n\n$app.prompt(\"analyze code\")\n  -\u003e .contains(\"ERROR\") ? $app.error() ! $app.process()\n```\n\n### Bounded Loops\n\nThe `do\u003climit: N\u003e` construct option caps loop iterations. `seq` and `fan` enforce a built-in 10,000-iteration ceiling. The host stays in control.\n\n```rill\n# Retry until non-empty, bail after 5 attempts\nuse\u003cext:app\u003e =\u003e $app\n\n\"\" -\u003e do\u003climit: 5\u003e {\n  $app.prompt(\"Generate a summary\")\n} while ($ == \"\")\n```\n\n```rill\n# Bounded iteration\n$items -\u003e seq({ \"Processing: {$}\" -\u003e log })\n```\n\n### Parallel Execution\n\nFan out work concurrently. Results preserve order.\n\n```rill\n# Parallel fan-out with closure\nuse\u003cext:app\u003e =\u003e $app\n\n[\"security\", \"performance\", \"style\"] -\u003e fan(|aspect| {\n  $app.prompt(\"Review for {$aspect} issues\")\n})\n```\n\n```rill\n# Parallel filter with method\n[\"critical bug\", \"minor note\", \"critical fix\"] -\u003e filter({ .contains(\"critical\") })\n```\n\n### Closures\n\nFirst-class functions with captured environment.\n\n```rill\n|x| ($x * 2) =\u003e $double\n[1, 2, 3] -\u003e fan($double)  # [2, 4, 6]\n5 -\u003e $double               # 10\n```\n\n### Dataflow Syntax\n\nData flows forward through pipes. Host extensions are hoisted with `use\u003cext:name\u003e =\u003e $var`, then invoked via dotted access.\n\n```rill\nuse\u003cext:app\u003e =\u003e $app\n\n$app.prompt(\"analyze this code\") -\u003e .trim -\u003e log\n```\n\n### String Interpolation\n\nEmbed expressions in strings. Triple-quotes for multi-line.\n\n```rill\n\"world\" -\u003e \"Hello, {$}!\" -\u003e log  # Hello, world!\n```\n\n```rill\n\"x + 1\" =\u003e $code\n\"\"\"\nAnalyze: {$code}\nReturn: PASS or FAIL\n\"\"\"\n```\n\n## Designed for LLM Codegen\n\nThese aren't arbitrary constraints — they're guardrails for reliable codegen.\n\n| Design choice | Codegen rationale |\n|---------------|-------------------|\n| **No null/undefined** | Eliminates the edge cases LLMs most frequently hallucinate |\n| **No truthiness** | Forces explicit boolean checks — no silent type coercion bugs |\n| **Value semantics** | Deep copy, deterministic equality. Safe for serialization, caching, replay |\n| **Immutable scoping** | Parent variables are read-only in child scopes. Prevents state drift across iterations |\n| **`$` prefix on variables** | Single-pass parsing, no symbol table. `name()` is a host function, `$name` is a variable — zero ambiguity |\n| **Type locking** | Variables lock type on first assignment. Catches type hallucinations at the assignment site |\n| **Linear error handling** | No try/catch, no unwinding. `assert` and `error` are terminal — easy for models to place correctly |\n| **Loops as expressions** | `fold`, `seq`, `while (cond) do { }` return state instead of mutating it. Aligns with step-by-step LLM reasoning |\n\n## What Our Target Users Say\n\nWe asked LLMs to review rill. They had opinions.\n\n\u003e \"Disciplined to the point of stubbornness, but in a good way. It trades familiarity for predictability.\"\n\u003e — ChatGPT\n\n\u003e \"You've basically banned the most common footguns in scripting languages.\"\n\u003e — Gemini\n\n\u003e \"It's possibly the first language I've seen where humans are the secondary audience.\"\n\u003e — Claude\n\n## Core Syntax\n\n| Syntax | Description |\n|--------|-------------|\n| `-\u003e` | Pipe data forward |\n| `=\u003e` | Capture and continue |\n| `$` | Current pipe value |\n| `.field` | Property access on `$` |\n| `cond ? a ! b` | Conditional |\n| `while (cond) do { }` | While loop |\n| `do { } while (cond)` | Do-while loop |\n| `do\u003climit: N\u003e { }` | Bounded loop construct option |\n| `seq`, `fan`, `filter` | Collection operator callables |\n| `fold(init, body)` | Reduction |\n| `acc(init, body)` | Scan (intermediate accumulator values) |\n| `\\|args\\| { }` | Closure |\n\n## Use Cases\n\n- **User-defined workflows.** Let power users script automation without exposing arbitrary code execution.\n- **Multi-phase pipelines.** Chain LLM calls with review gates between each step.\n- **Parallel agent fan-out.** Launch specialist agents concurrently, collect structured results.\n- **Edit-review loops.** Iterate until approval or `do\u003climit: N\u003e` max attempts.\n\nSee [Examples](docs/guide-examples.md) for complete workflow patterns.\n\n## Documentation\n\nSee [docs/index.md](docs/index.md) for full navigation.\n\n| Document | Description |\n|----------|-------------|\n| [Guide](docs/guide-getting-started.md) | Beginner introduction |\n| [Reference](docs/ref-language.md) | Language specification |\n| [Examples](docs/guide-examples.md) | Workflow patterns |\n| [Host Integration](docs/integration-host.md) | Embedding API |\n| [Bundled Extensions](docs/bundled-extensions.md) | Core extensions (fs, fetch, exec, kv, crypto) |\n| [Developing Extensions](docs/integration-extensions.md) | Writing custom extensions |\n| [Design Principles](docs/topic-design-principles.md) | Why rill works the way it does |\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frcrsr%2Frill","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frcrsr%2Frill","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frcrsr%2Frill/lists"}