First off, thanks for your interest in contributing to BAML! We appreciate all the help we can get in making it the best way to build any AI agents or applications.
📚 For comprehensive development setup instructions, see our Development Setup Guide
- Contributing to BAML
- Join our Community:
- Please join our Discord and introduce yourself in the
#contributingchannel. Let us know what you're interested in working on, and we can help you get started.
- Check Existing Issues:
- Look at the issue tracker and find and issue to work on.
Issues labeled
good first issueare a good place to start.
- Creating an Issue:
- If you find a bug or have a feature request, please tell us about in the discord channel and then open a new issue. Make sure to provide enough details and include a clear title.
- Fork the Repository:
- Fork the repository and clone your fork locally. Work on your changes in a feature branch.
- Submit a Pull Request (PR):
- Submit your pull request with a clear description of the changes you've made. Make sure to reference the issue you're working on.
-
Fix parsing issues: PR #1031
-
Coerce integers properly: PR #1023
-
Fix syntax highlighting and a grammar parser crash: PR #1013
-
Implement literal types (e.g.,
sports "SOCCER" | "BASKETBALL"): PR #978 -
Fix issue with OpenAI provider: PR #896
-
Implement
maptype: PR #797
We use mise to manage development tools and ensure everyone has the correct versions.
-
Run the setup script:
./scripts/setup-dev.sh
This will:
- Install mise (if not already installed)
- Install all required tools with correct versions (Rust 1.85.0, Go 1.23, Python 3.12, Ruby 3.2.2, Node.js LTS)
- Install language-specific tools (cargo-watch, wasm-pack, protoc-gen-go, etc.)
- Set up Python and Ruby dependencies
-
Verify installation:
mise list
-
Update tools (when
mise.tomlchanges):mise install
The setup script automatically handles all dependencies and version management, ensuring a consistent development environment across all contributors.
<TBD — we will write more details here>
-
baml-cli/ VSCodegeneratesbaml_client, containing all the interfaces people use to call thebaml-runtime. -
Pest grammar -> AST (build diagnostics for linter) -> Intermediate Representation (IR): The runtime parses BAML files, builds and calls LLM endpoints, parses data into JSONish, and coerces that JSONish into the schema.
-
Run the setup script if you haven't already:
./scripts/setup-dev.sh
-
Run
cargo buildinengine/and make sure everything builds on your machine. -
Run some unit tests:
cd engine/baml-lib/baml/and runcargo testto execute grammar linting tests.
-
Run the integration tests.
-
Set up Git hooks (Recommended):
- Install the pre-commit hook to automatically format Rust code:
./tools/install-hooks
- This hook will run
cargo fmtwith import organization before each commit - If formatting changes are made, you'll need to review and re-commit the changes
- Install the pre-commit hook to automatically format Rust code:
Prerequisites:
- Node.js 20.x or later
- Rust (stable toolchain)
- Go 1.23 or later
- Python 3.12
- Git
The script automatically handles installing missing tools and dependencies, so you can run it on a fresh machine.
The integration tests verify BAML's functionality across multiple programming languages. Each language has its own test suite in the integ-tests/ directory.
- Rust toolchain (managed by mise)
- BAML CLI (built from source or installed)
You can set up environment variables in two ways:
-
Using .env file (Recommended for external contributors):
- Create a
.envfile in theinteg-testsdirectory - Required variables:
OPENAI_API_KEY=your_key_here # Add other provider keys as needed: # ANTHROPIC_API_KEY=your_key_here # AWS_ACCESS_KEY_ID=your_key_here # etc.
- Create a
-
Using Infisical (BAML internal use only, use this if infisical is available):
- Install Infisical CLI
- Use the
infisical runcommands shown in examples below - External contributors should replace
infisical run --env=test --withdotenv -e ../.env --in all commands
-
Install prerequisites:
- Node.js (Latest LTS, managed by mise)
- pnpm package manager (managed by mise)
-
Build the TypeScript runtime:
cd engine/language_client_typescript
pnpm build:debug- Set up and run tests:
cd integ-tests/typescript
pnpm install
pnpm generate
dotenv -e ../.env -- pnpm integ-tests # or use infisical for internal BAML devs-
Install prerequisites:
- Python 3.8 or higher (3.12 recommended, managed by mise)
- uv package manager (installed via mise)
-
Set up the environment:
cd integ-tests/python
uv sync- Build and install the Python client:
# Note: env -u CONDA_PREFIX is needed if using Conda
uv run maturin develop --uv --manifest-path ../../engine/language_client_python/Cargo.toml- Generate client code and run tests:
uv run baml-cli generate --from ../baml_src
dotenv -e ../.env -- uv run pytest # or use infisical for internal BAML devs-
Prerequisites are handled by the setup script (Ruby 3.2.2 via mise)
-
Build the Ruby client:
cd integ-tests/ruby
(cd ../../engine/language_client_ruby && rake compile)- Install dependencies and generate client:
bundle install
baml-cli generate --from ../baml_src- Run tests:
dotenv -e ../.env -- rake test # or use infisical for internal BAML devs-
Define your BAML files in
integ-tests/baml_src/:- Add clients in
clients.baml - Add functions and tests in
test-files/providers/ - See BAML Source README for details
- Add clients in
-
Generate client code for each language:
# TypeScript
cd integ-tests/typescript && pnpm generate
# Python
cd integ-tests/python && uv run baml-cli generate --from ../baml_src
# Ruby
cd integ-tests/ruby && mise exec -- baml-cli generate --from ../baml_src-
Create language-specific test files:
- Follow the patterns in existing test files
- Use language-appropriate testing frameworks (Jest, pytest, Minitest)
- Include both success and error cases
- Test edge cases and timeouts
-
Run the tests in each language to ensure cross-language compatibility
Each language has its own debugging setup in VS Code:
-
TypeScript:
- Install Jest Runner extension
- Use launch configuration from TypeScript README
- Set
BAML_LOG=tracefor detailed logs
-
Python:
- Install Python Test Explorer
- Use launch configuration from Python README
- Use
-sflag to show print statements
-
Ruby:
- Install Ruby Test Explorer
- Use launch configuration from Ruby README
- Use verbose mode for detailed output
-
Navigate to the test directory:
cd engine/baml-runtime/tests/
-
Run tests with:
cargo test --features internal
This will run the baml-serve server locally, and ping it. You may need to change the PORT variable for your new test to use a different port (we don't have a good way of autoselecting a port).
Instructions for testing a particular OpenAPI client are TBD.
-
Test new syntax in the pest playground.
-
Update the following:
- Pest grammar: Modify the
.pestfile. - AST parsing: Update the AST parsing of the new grammar.
- IR: Modify the Intermediate Representation (IR).
- Pest grammar: Modify the
-
Ensure all tests pass:
- Run
cargo testinengine/baml-lib/ - Ensure integration tests still pass.
- Run
-
Modify the grammar for the PromptFiddle.com syntax rendering that uses Lezer, if necessary.
This requires a macos or linux machine, since we symlink some playground files between both PromptFiddle.com website app, and the VSCode extension itself.
Note: If you are just making changes to the VSCode extension UI, you may want to go to the section: Testing PromptFiddle.com.
-
Navigate to the TypeScript directory:
cd typescript/
-
Install dependencies:
pnpm i
-
Build and launch the extension:
pnpm build:vscode- Open VSCode and go to the Run and Debug section (play button near the extensions button).
- Select "Launch VSCode Extension" and press the play button.
- This will open a new VSCode window in Debug mode.
- You can open a simple BAML project in this window (refer to our quickstart guide to set up a simple project, or clone the
baml-examplesrepository).
-
Generate the language server binary (in case our scripts don't do this for you)
cd typescript/apps/vscode-extpnpm server:build
-
Reload the extension:
- Use
Command + Shift + Pto reload the extension when you change any core logic. - Alternatively, close and reopen the playground if you rebuild the playground.
- Use
To rebuild the playground UI:
- Navigate to the shared playground components:
cd typescript/packages/playground-common - Make your changes
- Build:
pnpm build - Close and open the playground in your "Debug mode VSCode window"
Testing promptfiddle.com
This is useful if you want to iterate faster on the Extension UI, since it supports hot-reloading.
-
Navigate to the Fiddle Web App directory:
cd typescript/apps/fiddle-web-app
-
Start the dev server:
pnpm dev
-
The app will hot-reload when you modify files in:
typescript/packages/playground-common(shared playground components)typescript/packages/ui(shared UI components)typescript/apps/fiddle-web-app(app-specific code)