Skip to content

Releases: gram-lang/gram

v.1.3.0

Choose a tag to compare

@abiwab abiwab released this 29 Sep 17:18

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 as càs, càc or fl oz

Bug fixes and improvements

  • CLI / View: Fixed several display issues in gram view and 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 like 1h4.5.
    • The resting time now appears in the recipe header.
    • Common fractions such as 1/4 tsp stay fractions in the shopping list instead of becoming 0.3.
  • 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.yaml isn't spelled exactly like the recipe name, such as "Huile d'olive" stored under huile-dolive:
    • Volumes like @Huile d'olive{10ml} are now converted to grams and no longer trigger "ingredient missing nutrition data"
    • gram db lint now reports ingredients whose names or aliases would be confused with each other
  • Modules & Rendering: Intermediates declared inside imported modules now show the name you wrote (for example pressed) instead of an internal path like tofu$marinated$pressed, in gram 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

Choose a tag to compare

@abiwab abiwab released this 25 Aug 21:18

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 print and 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

Choose a tag to compare

@abiwab abiwab released this 22 Aug 14:48

✨ New Features

  • Parser & Kitchen: Introduced modular recipes and multi-file imports via the @use directive:
    • 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 under paths: in .gram/config.yaml.
    • Added --stock CLI 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 @use import 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 diff and gram watch now 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 createMemoryHost from @gram-lang/modules for 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.
  • CLI: Added automatic update checking and a new gram upgrade command:
    • 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 upgrade to 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: false setting in config.yaml (or the GRAM_NO_UPDATE_CHECK environment 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 sync reports 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) to info severity 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

Choose a tag to compare

@abiwab abiwab released this 16 Aug 21:02

✨ 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 .gram recipes.
    • Automatically populates title:, author: (channel name), and source: 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_KEY is configured.
  • 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-model CLI 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 import hanging in non-interactive environments when --output was used without --yes.
  • CLI / Database: Added physical coherence and sanity checks across gram db validate and gram db enrich:
    • gram db validate checks calorie consistency against Atwater estimates (4 kcal/g protein/carbs, 9 kcal/g fat, 7 kcal/g alcohol).
    • gram db validate checks sub-macro coherence (sugars exceeding total carbs, fat sub-types exceeding total fat).
    • gram db validate enforces category-based density sanity ranges and unit weight bounds.
    • gram db enrich constrains AI estimates within physical limits and prompts self-verification of Atwater consistency.
    • gram db enrich passes known ingredient categories to the AI to reduce guesswork.
  • CLI / Database: gram db enrich now walks you through an interactive review before writing AI estimates to ingredients.yaml:
    • Preview, accept, edit, or skip AI-proposed density, unit weight, and nutrition values per ingredient.
    • Unedited AI values are tagged with # [LLM] in ingredients.yaml to track provenance.
    • Added --report (-r) to preview needed database enrichments without writing changes, matching gram 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: and source: fields.
    • Redirected progress indicators to stderr so stdout redirection (gram import ... > recipe.gram) produces clean recipe files.
  • 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-100g nutrition basis calculated from raw assembled recipe mass.
    • Added the --nutrition <auto|total|per-portion|per-100g> option to gram view, gram export, and gram 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).

🐛 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 enrich can 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

Choose a tag to compare

@abiwab abiwab released this 07 Aug 18:25

1.0.1 - 2026-08-07

🐛 Bug Fixes & Improvements

  • Fixed the --help description of gram check to clarify that it also checks database completeness by default, unless --skip-db is 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 sync as the recommended next step.
    • It accurately reports any remaining compiler warnings (e.g., missing ingredients) instead of silently discarding them.
  • Fixed gram init to ensure the interactive AI provider setup accurately offers the currently recommended models (e.g., llama4).

v.1.0.0

Choose a tag to compare

@abiwab abiwab released this 06 Aug 11:37

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

v.0.4.0-alpha Pre-release
Pre-release

Choose a tag to compare

@abiwab abiwab released this 04 Jan 18:26

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 totalTime vs activeTime metrics.
  • 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

v.0.3.1-alpha Pre-release
Pre-release

Choose a tag to compare

@abiwab abiwab released this 03 Jan 13:32

Minor updates

  • Docs: Updated README.md files 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

v.0.3.0-alpha Pre-release
Pre-release

Choose a tag to compare

@abiwab abiwab released this 02 Jan 20:03

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 (formerly gram-parser).
    • packages/compiler: Compiler and graph logic (formerly gram-compiler).
    • packages/playground: The web-based IDE.
    • packages/vscode-extension: Visual Studio Code language support.
  • Workspace Management: The root package.json now acts as a workspace manager, allowing installation of all dependencies with a single npm install command.
  • Centralized Config: Introduced a shared tsconfig.base.json to 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...).

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.md and CONTRIBUTING.md to 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.json scripts.

How to test this release

  1. Clone the repo (or pull changes).
  2. Run npm install at the root.
  3. Run npm run build.
  4. Run npm run dev.
  5. Open http://localhost:3000 and try the playground.

v0.2.0-alpha

v0.2.0-alpha Pre-release
Pre-release

Choose a tag to compare

@abiwab abiwab released this 30 Dec 17:53

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 the dist/ directory.

No changes were made to the .gram grammar itself.