{"id":49170294,"url":"https://github.com/juxt/allium","last_synced_at":"2026-04-22T18:03:20.507Z","repository":{"id":337297149,"uuid":"1142002519","full_name":"juxt/allium","owner":"juxt","description":"Velocity through clarity","archived":false,"fork":false,"pushed_at":"2026-04-20T21:02:05.000Z","size":624,"stargazers_count":282,"open_issues_count":1,"forks_count":14,"subscribers_count":10,"default_branch":"main","last_synced_at":"2026-04-20T23:10:53.725Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://juxt.github.io/allium/","language":"JavaScript","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/juxt.png","metadata":{"files":{"readme":"README.md","changelog":null,"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-25T19:49:03.000Z","updated_at":"2026-04-20T21:54:21.000Z","dependencies_parsed_at":"2026-03-31T10:01:17.687Z","dependency_job_id":null,"html_url":"https://github.com/juxt/allium","commit_stats":null,"previous_names":["juxt/allium"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/juxt/allium","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juxt%2Fallium","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juxt%2Fallium/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juxt%2Fallium/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juxt%2Fallium/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/juxt","download_url":"https://codeload.github.com/juxt/allium/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juxt%2Fallium/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32148184,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-22T17:06:48.269Z","status":"ssl_error","status_checked_at":"2026-04-22T17:06:19.037Z","response_time":58,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2026-04-22T18:03:19.800Z","updated_at":"2026-04-22T18:03:20.501Z","avatar_url":"https://github.com/juxt.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# Allium\n\n*Velocity through clarity*\n\n---\n\nFeed your AI something healthier than Markdown. [juxt.github.io/allium](https://juxt.github.io/allium/)\n\n## Get started\n\nAllium works with Claude Code, Copilot, Cursor, Windsurf, Aider, Continue and 40+ other tools. How you install depends on your editor, but the skills are the same everywhere.\n\n**Claude Code** via the [JUXT plugin marketplace](https://github.com/juxt/claude-plugins):\n\n```\n/plugin marketplace add juxt/claude-plugins\n/plugin install allium\n```\n\n**Cursor, Windsurf, Aider, Continue and other skills-compatible tools:**\n\n```\nnpx skills add juxt/allium\n```\n\n**GitHub Copilot** reads skills and agents from the repository automatically. No installation needed.\n\n**Other editors:** If your editor doesn't read from `.agents/skills/`, symlink the installed skills into wherever it does look (e.g. `ln -s .agents/skills/allium .continue/rules/allium`, or `mklink /J` on Windows). Use a symlink rather than copying; the skill files contain relative links to reference material that a copy would break.\n\nOnce installed, type `/allium` to get started. Allium examines your project and guides you toward the right skill, whether that's distilling a spec from existing code or building one through conversation. Once you're familiar with the individual skills, you'll likely invoke them directly.\n\nJump to what [Allium looks like in practice](#what-this-looks-like-in-practice).\n\n## Skills and agents\n\nAllium provides five skills, an entry point and two autonomous agents.\n\n| Skill | Purpose |\n|---|---|\n| `/allium \u003cprompt\u003e` | Entry point. Examines your project or the prompt and routes you to the right skill. |\n| `/elicit \u003cfeature idea\u003e` (or `/allium:elicit`) | Build a spec through structured conversation. |\n| `/distill \u003ccodebase area\u003e` (or `/allium:distill`) | Extract a spec from existing code. |\n| `/propagate \u003coptional constraints\u003e` (or `/allium:propagate`) | Generate tests from a spec. |\n| `/tend \u003coptional constraints\u003e` (or `/allium:tend`) | Targeted changes to existing specs. |\n| `/weed \u003coptional constraints\u003e` (or `/allium:weed`) | Find and fix divergences between spec and code. |\n\nHow skills appear depends on your editor. Some show the fully qualified form (`/allium:weed`), others show the short form (`/weed`), and some support both. If one form isn't recognised, try the other. Skills also auto-trigger when you open or edit `.allium` files.\n\nTend and weed are also available as autonomous **agents** that run in their own context, keeping Allium syntax out of your main session. Claude Code picks up agents from `agents/`, Copilot from `.github/agents/`. How editors discover skills and agents is still settling; we make these available in the most portable formats we can and expect to consolidate as conventions stabilise. If your editor doesn't pick something up, [raise an issue](https://github.com/juxt/allium/issues).\n\nFor larger codebases, distillation and other ambitious tasks may need several passes to capture everything. Consider an iterative approach like the [Ralph Wiggum loop](https://ghuntley.com/ralph/), repeating until there's nothing further to do.\n\n## Why not just point the LLM at the code?\n\nWithin a session, meaning drifts: by prompt ten or twenty, the model is pattern-matching on its own outputs rather than the original intent. Across sessions, knowledge evaporates entirely. Modern LLMs navigate codebases effectively, but the limitation appears when you need to distinguish what the code *does* from what it *should do*. Code captures implementation, including bugs and expedient decisions. The model treats all of it as intended behaviour.\n\nPrecise prompting helps, but precise prompting means specifying intent: which behaviours are deliberate, which constraints must be preserved. You end up writing descriptions of intent distributed across your prompts. Allium captures this in a form that persists. The next engineer, or the next model, or you next week, can understand what the system does and what it was meant to do.\n\n## Why not capture requirements in markdown?\n\nMarkdown provides no framework for surfacing ambiguities and contradictions. You can write \"users must be authenticated\" in one section and \"guest checkout is supported\" in another without the format highlighting the tension. Capable models may resolve such ambiguities silently in ways you didn't intend; weaker models may not recognise that alternatives existed.\n\nAllium's structure makes contradictions visible. When two rules have incompatible preconditions, the formal syntax exposes the conflict. The model doesn't need to be clever enough to spot the issue in prose; the structure does that work.\n## Iterating on specifications\n\nThe specification and the code evolve together. Writing and refining a behavioural model alongside implementation deepens your understanding of both the problem and your solution. Questions surface that you wouldn't have thought to ask; constraints emerge that only become visible when you try to formalise them.\n\nTwo processes feed this growth: **elicitation** works forward from intent through structured conversations with stakeholders, while **distillation** works backward from implementation to capture what the system actually does, including behaviours that were never explicitly decided. When distillation and elicitation diverge, you've found something worth investigating.\n\nSee the [elicitation guide](skills/elicit/SKILL.md) and the [distillation guide](skills/distill/SKILL.md) for detailed approaches.\n\n## On single sources of truth\n\nA common objection is that maintaining behavioural models alongside code violates the single source of truth principle. But code captures both intentional and accidental behaviour, with no mechanism to distinguish them. Is that authentication quirk a feature or a bug? The code can't tell you. You need something outside the code to even articulate \"this behaviour is wrong\". Engineers already accept this in other contexts: type systems express intent that code must satisfy, tests assert expected behaviour against actual behaviour. These aren't duplication. The gap between spec and code surfaces questions you need to answer, and that redundancy is what makes the system resilient.\n\n## What Allium captures\n\nAllium provides a minimal syntax for describing events with their preconditions and the outcomes that result. The language deliberately excludes implementation details such as database schemas and API designs, focusing purely on observable behaviour.\n\n```allium\nrule RequestPasswordReset {\n    when: UserRequestsPasswordReset(email)\n\n    let user = User{email}\n\n    requires: exists user\n    requires: user.status in {active, locked}\n\n    ensures:\n        for t in user.pending_reset_tokens:\n            t.status = expired\n    ensures:\n        let token = PasswordResetToken.created(\n            user: user,\n            created_at: now,\n            expires_at: now + config.reset_token_expiry,\n            status: pending\n        )\n        Email.created(\n            to: user.email,\n            template: password_reset,\n            data: { token: token }\n        )\n}\n```\n\nThis rule captures observable behaviour: when a password reset is requested, if the email matches an active or locked account, existing tokens are invalidated, a new token is created and an email is sent. It says nothing about which database stores the token or which service sends the email, because those decisions belong to implementation.\n\nThe same syntax works whether you're capturing infrastructure contracts or operational policy. A circuit breaker specification describes behaviour that typically lives in library defaults, Grafana alerts and architecture docs, never in any formal specification:\n\n```allium\nentity CircuitBreaker {\n    service: ExternalService\n    status: closed | open | half_open\n    opened_at: Timestamp?\n    failures: Failure with circuit_breaker = this\n    recent_failures: failures where occurred_at \u003e now - config.failure_window\n    failure_rate: recent_failures.count / config.window_sample_size\n    is_tripped: failure_rate \u003e= config.failure_threshold\n}\n\nconfig {\n    failure_threshold: Decimal = 0.5\n    failure_window: Duration = 30.seconds\n    window_sample_size: Integer = 20\n    recovery_timeout: Duration = 10.seconds\n}\n\nrule CircuitOpens {\n    when: circuit_breaker: CircuitBreaker.is_tripped\n    requires: circuit_breaker.status = closed\n\n    ensures:\n        circuit_breaker.status = open\n        circuit_breaker.opened_at = now\n}\n\nrule CircuitProbes {\n    when: circuit_breaker: CircuitBreaker.opened_at + config.recovery_timeout \u003c= now\n    requires: circuit_breaker.status = open\n\n    ensures: circuit_breaker.status = half_open\n}\n```\n\nThe [language reference](references/language-reference.md) covers entities, rules, triggers, relationships, projections, derived values, surfaces and actor declarations. The [v1 to v2 migration guide](references/migration-v1-to-v2.md) and [v2 to v3 migration guide](references/migration-v2-to-v3.md) cover what changed between versions and how to upgrade existing specs.\n\nAllium has no compiler and no runtime. It is purely descriptive, defined entirely by its documentation. LLMs already function as pseudocode compilers, executing informal descriptions into working code. A well-structured behavioural language ensures that what gets compiled is what you actually meant. The behavioural model is the primary artefact; the code that implements it is secondary.\n\n## What this looks like in practice\n\n### Allium surfaces implications you missed\n\nA customer's account was suspended for a terms of service violation. They've appealed and the team wants to let them back in.\n\n---\n\n\u003e ***\u003e A customer says they can't reset their password. Their account was suspended last month but they've appealed and we want to let them back in. Can you enable password reset for suspended users?***\n\u003e\n\u003e ✻ Your Allium requires `user.status in {active, locked}` for password resets. This user's status is `suspended`, so the reset is blocked by design. Reactivating through password reset would bypass your `AccountReinstated` rule, which requires admin approval and logs an audit trail.\n\u003e\n\u003e ✻ Should we reinstate the account through the existing admin flow first, then let them reset their password? Or create a new `AccountReinstatedViaAppeal` rule that combines both steps with the audit trail intact?\n\u003e\n\u003e ***\u003e Reinstate through the admin flow first. The audit trail matters.***\n\n---\n\nWithout Allium, the LLM would have relaxed the status check, accidentally creating a backdoor around an admin control. The behavioural model caught that password reset and account reinstatement are separate concerns with different approval requirements.\n\n### Knowledge persists across sessions\n\nA developer starts a new session days later, working on a different feature.\n\n---\n\n\u003e ***\u003e Add a free trial. New subscribers get their first month at no charge.***\n\u003e\n\u003e ✻ Your Allium has a constraint here. `SubscriptionCreated` ensures a payment is processed and `InvoiceGenerated` requires `invoice.amount \u003e 0`. A free first month would need to bypass both.\n\u003e\n\u003e ✻ Should the trial skip invoice generation entirely, or create a zero-value invoice for the audit trail? And should the `PaymentMethod` still be captured upfront, or only when the trial converts?\n\u003e\n\u003e ***\u003e Create a zero-value invoice and capture the payment method upfront.***\n\n---\n\nThe developer never mentioned invoicing or payment method capture. The Allium did, from a session that ended days ago. Without it, the LLM would have implemented the trial with no awareness of these constraints, and the gaps would have surfaced in production.\n\n## Verification\n\nWhen the [Allium CLI](https://github.com/juxt/allium-tools) is installed, `.allium` files are validated automatically after every write or edit. Install it via Homebrew (`brew tap juxt/allium \u0026\u0026 brew install allium`) or Cargo (`cargo install allium-cli`). Diagnostics appear inline and the model fixes issues in the same turn. Without the CLI the skill falls back to the language reference, so installing it is recommended if you're working with Allium regularly.\n\n## Language governance\n\nEvery change to Allium is debated by a [nine-member review panel](https://github.com/juxt/allium/blob/proposals/TEAM.md) before adoption. Each panellist represents a distinct design priority: simplicity, machine reasoning, composability, readability, formal rigour, domain modelling, developer experience, creative ambition and backward compatibility. The panel exists to surface tensions that any single perspective would miss.\n\nThe panel operates in two modes. [Reviews](https://github.com/juxt/allium/blob/proposals/REVIEW.md) evaluate fixes to rough edges in the existing language, where the default is to fix the problem if a good fix exists. [Proposals](https://github.com/juxt/allium/blob/proposals/PROPOSE.md) evaluate new features and ambitious changes, where the default is to leave the language alone unless the case for change is strong. Both follow the same debate protocol: present, respond, rebut, synthesise, verdict.\n\n## Feedback\n\nWe'd love to hear how you get on with Allium. Success stories, rough edges, missing features, things that surprised you. Drop us a line at [info@juxt.pro](mailto:info@juxt.pro) or [raise an issue](https://github.com/juxt/allium/issues) if you have a specific request.\n\n## About the name\n\nAllium is the botanical family containing onions and shallots. The name continues a tradition in behaviour specification tooling: Cucumber and Gherkin established botanical naming as a convention in behaviour-driven development, followed by tools like Lettuce and Spinach.\n\nThe phonetic echo of \"LLM\" is intentional, reflecting where we expect these models to be most useful. \"Know your onions\" means to understand a subject thoroughly, and Allium consolidates scattered intent into an explicit form that models can reference reliably.\n\nLike its namesake, working with Allium may produce tears during the peeling, but never at the table.\n\n## Star History\n\n\u003ca href=\"https://www.star-history.com/?repos=juxt%2Fallium\u0026type=date\u0026legend=top-left\"\u003e\n \u003cpicture\u003e\n   \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.star-history.com/image?repos=juxt/allium\u0026type=date\u0026theme=dark\u0026legend=top-left\" /\u003e\n   \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://api.star-history.com/image?repos=juxt/allium\u0026type=date\u0026legend=top-left\" /\u003e\n   \u003cimg alt=\"Star History Chart\" src=\"https://api.star-history.com/image?repos=juxt/allium\u0026type=date\u0026legend=top-left\" /\u003e\n \u003c/picture\u003e\n\u003c/a\u003e\n\n---\n\n## Copyright \u0026 License\n\nThe MIT License (MIT)\n\nCopyright © 2026 JUXT Ltd.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuxt%2Fallium","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjuxt%2Fallium","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuxt%2Fallium/lists"}