Repository navigation
Releases: gram-lang/gram
Release list
v.1.3.0
New features
- CLI / Requirements: The CLI now requires Node.js 22 or later (Bun keeps working as before).
- Parser & Kitchen: Units written with abbreviation dots are now understood:
{1/2 c.à.s},{1 c. à c.},{2 fl. oz.}and similar spellings now parse and are recognized as the same unit ascàs,càcorfl oz
Bug fixes and improvements
- CLI / View: Fixed several display issues in
gram viewand cook mode:- Timers now show their real unit (
~{1h}is shown as~1h,~{20s}as~20s) instead of always "min". - Recipe durations are rounded and readable (
1h 5m,25m 5s) instead of raw decimals like1h4.5. - The resting time now appears in the recipe header.
- Common fractions such as
1/4 tspstay fractions in the shopping list instead of becoming0.3.
- Timers now show their real unit (
- Modules: Fixed a misleading error message: a syntax error in the recipe you are editing was reported as coming from an "imported module", even when the recipe imports nothing. It now shows the plain syntax error, and the "imported module" wording is kept only for errors that really are in an imported file.
- Analyzer: Fixed ingredients being ignored for density conversion and nutrition when their entry in
ingredients.yamlisn't spelled exactly like the recipe name, such as "Huile d'olive" stored underhuile-dolive:- Volumes like
@Huile d'olive{10ml}are now converted to grams and no longer trigger "ingredient missing nutrition data" gram db lintnow reports ingredients whose names or aliases would be confused with each other
- Volumes like
- Modules & Rendering: Intermediates declared inside imported modules now show the name you wrote (for example
pressed) instead of an internal path liketofu$marinated$pressed, ingram view, HTML and Markdown output.
Breaking
- CLI: Node.js 20 reached end of life in April 2026 and is no longer supported: upgrade to Node.js 22+ before updating the CLI
Fixed
- Parser: A quantity in braces that can't be read (for example
@salt{1 g/l}or a missing}) is now reported as an error pointing at the brace, instead of being ignored and merging the ingredient with others that share the same first word
v.1.2.1
Bug fixes and improvements
- Renderer: Switched icons to embedded inline SVGs, removing external CDN dependencies (
unpkg.com) and enabling full offline previews in VS Code. - CLI / Export: Fixed missing ingredient quantities in
gram printand HTML exports (gram export --format html). - Documentation & Playground: Improved accessibility and keyboard navigation across the website and interactive playground (ARIA roles, tab navigation,
prefers-reduced-motion).
v.1.2.0
✨ New Features
- Parser & Kitchen: Introduced modular recipes and multi-file imports via the
@usedirective:- Import external base recipes directly into a recipe using
@use "./bases/shortcrust-pastry.gram" as &shortcrust. - Imported steps seamlessly interleave into the global ALAP scheduling timeline, preserving resting times and dependencies.
- Automatically scales imported base quantities when referenced with specific yields (e.g.
&shortcrust{250g}halves a 500 g base recipe). - Supports destructured multi-yield imports (e.g.
@use "./bases/tart-elements.gram" as { &crust, &frangipane }) scaling each component independently. - Supports multi-word bindings using bracket notation (e.g.
@use "..." as &pastry dough{}). - Resolves project-root paths (
@/bases/...) and custom path aliases defined underpaths:in.gram/config.yaml. - Added
--stockCLI flag to treat pre-made base imports as stock items (zero timeline overhead, single shopping list line, retaining full nutritional totals). - Supports retro-planning timeline offsets directly on
@useimport lines (e.g.@use "./bases/levain-starter.gram" as &starter ~{-2d}). - Spliced sections in HTML, Markdown, and print outputs display origin badges crediting their source module.
gram diffandgram watchnow track import additions, removals, rebinding, rescaling, and dependency file changes.- Language Server and VS Code extension support live dependency composition, Go to Definition into base files, path auto-completion, and quick-fix diagnostics for missing exports.
- Exported
createMemoryHostfrom@gram-lang/modulesfor browser and in-memory module graph resolution. - Corrected whole-recipe mass and nutrition totals to accurately include spliced intermediate (
-> &) masses. - Normalized rescaled ingredient quantities to one decimal place for display consistency across all outputs.
- Import external base recipes directly into a recipe using
- CLI: Added automatic update checking and a new
gram upgradecommand:- gram now checks npm in the background and prints a short "update available" notice after a command finishes (skipped in CI and non-interactive runs).
- Added
gram upgradeto check for and install the latest version on demand — it always performs a fresh check and asks for confirmation before running the install. - Added an
updateCheck: falsesetting inconfig.yaml(or theGRAM_NO_UPDATE_CHECKenvironment variable for a single run) to opt out of the passive notice.
- Parser & Kitchen: Composite ingredients written with a short, generic child name (like
@juice<@lemon) are now protected against a silent ingredient-database mix-up:- The compiler now warns when the same short composite name (e.g. "juice") is drawn from two different parents within one recipe (lemon in one step, orange in another) — until now this went unnoticed and the two usages silently shared one entry in the ingredient database.
gram db syncreports the same conflict across your whole recipe collection, so two unrelated recipes that happen to use the same generic composite name don't overwrite each other's nutrition and density data.- The AI recipe importer (
gram import) now writes composite ingredients with their full name (e.g. "lemon juice") instead of a short generic one, so newly imported recipes don't create this conflict in the first place.
🐛 Bug Fixes & Improvements
- Parser & Kitchen: Fixed
gram scale(and any other caller that re-scales an already-compiled recipe) silently leaving alternative ingredient groups (@butter|@margarine) and composite parent-draw quantities (@egg-yolks{2}<@eggs{3}) unscaled. - Parser & Kitchen: Improved clarity and tone for diagnostic messages and revised severity tiers:
- Reworded compiler and module diagnostic messages to provide actionable guidance and avoid alarmist phrasing for standard culinary approximations.
- Reclassified non-critical notices (
MISSING_MACROS,UNKNOWN_MASS,TRACK_CONTENTION) toinfoseverity so they do not clutter warning counters. - Enhanced Playground and editor diagnostic styling with dedicated color schemes for errors (red), warnings (amber), and notices (blue).
- Language Server: Normalized error states and unified diagnostic handling across Playground and VSCode extensions:
- Unified Playground diagnostics into a centralized full-width debug console with filter pills and interactive jump-to-location navigation.
- Added mobile segmented tab navigation (
[Editor]/[Preview]) and responsive single-row toolbar layout for mobile viewports. - Resolved nutrition diagnostics disconnection in the analyzer by merging physical and nutritional warnings into primary compiler warnings — the editor only turns these into squiggles when they carry a real position, so an incomplete-nutrition notice no longer misplaces itself at the top of the file.
- Markdown and print HTML exports keep their explicit "incomplete data" note next to the affected nutrition figures; the interactive HTML preview conveys the same gap through its coverage badge instead.
- A scale-target that fails to resolve (e.g. an unconvertible unit) now correctly turns the Playground's status badge and error panel red instead of being undersold as a warning, without marking the file tab as if the recipe itself had a syntax error.
- The Playground diagnostics console no longer gets stuck filtered on a category that just emptied out (e.g. after fixing the warning it was showing).
- Resolved silent compilation failures in the Language Server by capturing pipeline exceptions and pushing actionable error notifications to webviews — including when the thrown error carries no message, which previously slipped past the check silently.
- A compile-time failure (parses fine, but
compile()/analyze()throws) now also surfaces as an editor diagnostic, not only as a webview notification, so it's still visible with the preview panel closed. - Added bidirectional webview messaging in the VSCode extension to jump directly to error offsets in the active editor.
- Localized the Playground diagnostics console's collapse/expand tooltip, previously hardcoded in French regardless of site locale.
- Parser & Kitchen: Fixed a false circular reference warning when multiple sections used percentage-of formulas on same-named ingredients by scoping cycle detection per section.
v.1.1.0
✨ New Features
- CLI / Import: Support importing recipes directly from YouTube videos and Shorts via
gram import:- Uses Gemini multimodal video understanding to analyze cooking videos and generate structured
.gramrecipes. - Automatically populates
title:,author:(channel name), andsource:metadata from YouTube. - Automatically normalizes YouTube Shorts URLs to standard video formats.
- Added
--max-duration(default 20 minutes) to prevent accidental token overconsumption on long videos. - Displays upfront video duration and estimated token cost when
YOUTUBE_API_KEYis configured.
- Uses Gemini multimodal video understanding to analyze cooking videos and generate structured
- CLI / AI: Explicit AI model and provider selection for all AI commands (
gram import,gram db lint,gram db enrich):- Added
--model,--provider, and--pick-modelCLI flags to inspect or override the active model per run without altering persistent config. - The CLI now displays the active AI provider, model, and configuration source before execution.
- Isolated provider API keys so credentials configured for a specific provider are never leaked or reused when switching providers.
- Fixed
gram importhanging in non-interactive environments when--outputwas used without--yes.
- Added
- CLI / Database: Added physical coherence and sanity checks across
gram db validateandgram db enrich:gram db validatechecks calorie consistency against Atwater estimates (4 kcal/g protein/carbs, 9 kcal/g fat, 7 kcal/g alcohol).gram db validatechecks sub-macro coherence (sugars exceeding total carbs, fat sub-types exceeding total fat).gram db validateenforces category-based density sanity ranges and unit weight bounds.gram db enrichconstrains AI estimates within physical limits and prompts self-verification of Atwater consistency.gram db enrichpasses known ingredient categories to the AI to reduce guesswork.
- CLI / Database:
gram db enrichnow walks you through an interactive review before writing AI estimates toingredients.yaml:- Preview, accept, edit, or skip AI-proposed density, unit weight, and nutrition values per ingredient.
- Unedited AI values are tagged with
# [LLM]iningredients.yamlto track provenance. - Added
--report(-r) to preview needed database enrichments without writing changes, matchinggram db lint --report(replaces--dry-run/-n). - Added
--yes(-y) to accept all estimates automatically for non-interactive scripting. - Automatically falls back to accepting values with a warning when executed in non-interactive (non-TTY) environments.
- CLI / Import: Added integrity guardrails and diagnostic reporting to
gram import:- Validates compiled AST tokens against AI output to detect lost ingredients or truncated steps, aborting instead of writing corrupted files (overridable with
--force). - Reports uncorrected AI generation errors with actionable diagnostics.
- Identifies imported ingredients missing quantities and lists their line numbers for easy manual completion.
- Reports unknown database ingredients and unweighed units when an ingredient database is present.
- Prevented hallucinated placeholder metadata in
author:andsource:fields. - Redirected progress indicators to
stderrso stdout redirection (gram import ... > recipe.gram) produces clean recipe files.
- Validates compiled AST tokens against AI output to detect lost ingredients or truncated steps, aborting instead of writing corrupted files (overridable with
- Nutrition & Rendering: Support flexible nutrition serving bases (per portion and per 100 g) alongside whole-recipe totals:
- Declaring
portions:in recipe frontmatter now calculates per-portion nutrition and keeps values constant when scaling recipes. - Added a standardized
per-100gnutrition basis calculated from raw assembled recipe mass. - Added the
--nutrition <auto|total|per-portion|per-100g>option togram view,gram export, andgram print. - Added nutrition basis toggles in the web playground and VS Code live preview.
- Localized all nutrient names and table headers across supported languages (French and English).
- Declaring
🐛 Bug Fixes & Improvements
- Parser & Kitchen: Fixed an issue where multi-word composite ingredients marked with
&(e.g.@juice{1}<@&unwaxed lemon{}) were duplicated in the shopping list instead of being combined into a single purchase item. - Analyzer & Language Server: Improved nutrient calculation completeness and editor hover precision:
- Saturated, monounsaturated, polyunsaturated fats, and alcohol are now included in recipe nutrition totals instead of being omitted.
gram db enrichcan now propose monounsaturated and polyunsaturated fat values during ingredient enrichment.- Fixed the editor hover tooltip incorrectly displaying sodium in grams instead of milligrams.
- Analyzer: Fixed recipe total mass and section weights to include ingredients defined as relative percentages of another ingredient (e.g.
@water{60% @&flour}).
v.1.0.1
1.0.1 - 2026-08-07
🐛 Bug Fixes & Improvements
- Fixed the
--helpdescription ofgram checkto clarify that it also checks database completeness by default, unless--skip-dbis used. - Reduced the AI provider costs of running
gram import:- Prompt caching is now enabled, so retries reuse the cached prompt instead of paying full price.
- The command now sends a minimized recipe payload instead of the full raw webpage data.
- The self-correction loop no longer spends retries on informational warnings (like missing database ingredients).
- Formatting is now handled locally instead of spending an AI call to fix it.
- Improved the quality and correctness of recipes generated by
gram import:- Fixed an issue where English words would leak into non-English recipes.
- Fixed grammatical errors (dropped articles) around ingredient and cookware references in non-English output.
- Descriptive adjectives (like "boneless skinless") are now correctly extracted as preparation steps instead of creating unwieldy ingredient names.
- Corrected the generated syntax for multi-word cookware references.
- Fixed an issue where the target language was sometimes incorrectly inferred.
- Improved decoding of accented characters and punctuation from the source recipe.
- Improved the CLI guidance printed after running
gram import:- It now correctly points to
gram db syncas the recommended next step. - It accurately reports any remaining compiler warnings (e.g., missing ingredients) instead of silently discarding them.
- It now correctly points to
- Fixed
gram initto ensure the interactive AI provider setup accurately offers the currently recommended models (e.g., llama4).
v.1.0.0
Gram 1.0.0 is officially here! 🍊🎉
Hi everyone! Today is a big milestone: Gram v1.0.0 is officially out!
Following up on the last beta version, where I focused on test coverage and internal monorepo stability, there aren't really any new features in this release. Instead, this official 1.0 is more of a devlog update: it's all about setting up a proper, long-term home for Gram with a brand-new website, refreshed documentation, a new logo, and a switch to self-hosted infrastructure.
Recently, I shared Gram on Reddit, and the warm response and feedback I received really blew me away. Seeing people genuinely interested in the project (at least among food-loving devs!) gave me a huge boost of motivation to polish the last details, rebuild the site, and push this official 1.0 out the door. Thank you so much to everyone who reached out!
A Brand-New Website & Documentation
The most visible change with this release is that I completely rebuilt the website from the ground up using Astro and Starlight.
This switch allowed me to clean up the layout and overall organization of the documentation. Beyond the technical rework, I also took the opportunity to heavily revise the French documentation. Instead of keeping a strict line-by-line translation of the English manual, large parts of it have been rewritten to read much more naturally and fluidly.
I also added a dedicated blog to the site! I'll be using it to post news, project updates, and devlog articles. Finally, I took another pass at how Gram is introduced on the homepage so new visitors can get what the project is about right away. If you have any feedback on the new site or docs, please let me know!
A Fresh New Logo
Gram also has a new logo! Yes, it's already version #2... I redesigned it from scratch to keep it clean and readable even when scaled down to a tiny browser tab favicon.
The orange icon is a direct nod to my very first web project years ago. For retro gaming fans, it's also a (more or less) subtle tribute to the Japanese Dreamcast logo — my very first home console. It doesn't have anything to do with cooking, but it puts a smile on my face and brings back fond memories every time I look at it. So I guess that was reason enough to redesign it 😅
Self-Hosted Infrastructure & Open Collaboration
To keep Gram independent and maintain full control over it, I moved the canonical git repository from Codeberg to my own self-hosted Forgejo instance on a server located in France (git.gram-lang.org).
Setting up this whole infrastructure — server configuration, CI runners, and site deployment — took quite a bit of work, but having full ownership over the hosting environment gives me much more freedom to manage the project properly going forward.
That said, I want contributing to be as friction-free as possible. On the main Forgejo instance, you can log in directly using your GitHub account via OAuth, so there's no need to fill out a registration form or create yet another password. The repository is also automatically mirrored in real-time to both Codeberg and GitHub. I know creating accounts on new forges can be annoying, so feel free to open Issues or PRs on GitHub or Codeberg if you prefer — I'll keep an eye on all of them.
What's Next?
With v1.0.0, the foundations should be clean, reliable, and ready. Reaching this milestone feels great, and now I'm eager to get back to writing code!
My backlog is already filled with ideas, syntax improvements, and new features I can't wait to work on. I'll also be writing more general blog posts about Gram as a project, its roadmap, and where things are headed next.
Please give v1.0.0 a try, take a look at the new website, and feel free to reach out with any feedback. Happy cooking, and à bientôt !
v.0.4.0-alpha
Asynchronous tasks
What's New
⏱️ Asynchronous Tasks Support
You can now mark timers as asynchronous (background tasks) using the & modifier (e.g., ~{1h}&).
- Compiler: Calculates precise
totalTimevsactiveTimemetrics. - Playground: Visualize async tasks with specific styling (dashed borders, ⏳ icon) in both Markdown and Preview modes.
Synchronous timers represent active work that blocks the cook, while asynchronous timers (&) designate background tasks occurring in parallel. This distinction allows the compiler to accurately calculate real effort versus total duration and enables the generation of realistic Gantt charts.
Playground Improvements
- New AST View: Added a raw AST view mode to inspect the parser output.
- UI: Improved view selection with a new dropdown menu.
Bug Fixes
- Fixed an issue where multiple composite ingredients would not aggregate correctly in the shopping list.
Documentation
- Added "Tips" across the documentation to better explain the philosophy behind timers, cookware, and relative quantities.
v.0.3.1-alpha
Minor updates
- Docs: Updated
README.mdfiles with correct Playground URLs following the workspace migration. - Examples: Refined recipe examples to better showcase GRAM features.
Bug fix
- Fixed composite ingredient aggregation. Sub-ingredient quantities are now correctly summed across multiple sections, ensuring accurate parent ingredient totals in the shopping list.
v.0.3.0-alpha
Architecture Refactor
The project has been restructured to improve scalability, maintainability, and developer experience.
Key Changes
Major Restructuring
- The project structure has been completely reorganized. All code modules are now located in a centralized
packages/directory.packages/parser: Core parsing logic (formerlygram-parser).packages/compiler: Compiler and graph logic (formerlygram-compiler).packages/playground: The web-based IDE.packages/vscode-extension: Visual Studio Code language support.
- Workspace Management: The root
package.jsonnow acts as a workspace manager, allowing installation of all dependencies with a singlenpm installcommand. - Centralized Config: Introduced a shared
tsconfig.base.jsonto ensure consistent TypeScript configuration across all packages.
Separation of Parser & Compiler
- Decoupled Architecture: The Compiler logic has been extracted from the Parser.
- Parser (
packages/parser): Strictly responsible for grammar definition (OhmJS) and generating the raw AST. - Compiler (
packages/compiler): Responsible for semantic analysis, graph generation, and transforming the AST into usable artifacts (Shopping Lists, Instructions...).
- Parser (
This separation allows tools (like linters or syntax highlighters) to use the lightweight parser without pulling in the heavy compiler logic.
Developer Experience
- Global Scripts: Added unified commands at the project root for easier workflow:
npm run build: Builds the core (parser & compiler).npm run dev: Launches the Playground instantly.
- Clean Output: Build scripts now feature friendly emojis and concise logging 🏗️ ✅.
- Examples Library: Created a dedicated
examples/folder at the project root.- These examples are automatically synced with the Playground during build.
- The Playground now dynamically lists these examples in its dropdown menu.
Fixes & Polish
- Separated Parser and Compiler logic into distinct, clean packages with proper dependencies.
- Updated
README.mdandCONTRIBUTING.mdto reflect the new architecture.
Changes Breakdown
- Moved
gram-parser→packages/parser - Moved
gram-compiler→packages/compiler - Moved
playground→packages/playground - Moved
gram-vscode-extension→packages/vscode-extension - Added
tsconfig.base.json - Refactored root
package.jsonscripts.
How to test this release
- Clone the repo (or pull changes).
- Run
npm installat the root. - Run
npm run build. - Run
npm run dev. - Open
http://localhost:3000and try the playground.
v0.2.0-alpha
TypeScript Migration for gram-parser
This refactor migrates the entire gram-parser codebase from JavaScript to TypeScript to enhance project robustness and maintainability.
Key Changes:
- TypeScript: Converted all source files to TypeScript (
src/*.ts). - Strict Typing: Comprehensive interface definitions for the AST and internal compiler structures.
- Build: Added a compilation step (
npm run build) that generates JavaScript code and declaration files (.d.ts) in thedist/directory.
No changes were made to the .gram grammar itself.