Skip to content

Contributing to liter-llm

Thank you for your interest in contributing to liter-llm! This guide will help you get started with development.

This project uses Task for task automation and orchestration. Task is a task runner that simplifies development workflows across multiple languages and platforms.

Choose the installation method for your platform:

macOS (Homebrew):

Terminal window
brew install go-task

Linux:

Terminal window
# Using the installer script
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b ~/.local/bin
# Or via package managers:
apt install go-task # Debian/Ubuntu
pacman -S go-task # Arch

Windows:

Terminal window
# Using Scoop
scoop install task
# Or using Chocolatey
choco install go-task

For complete installation instructions, visit the official Task documentation.

After installing Task, set up your development environment:

Terminal window
# One-time setup - installs all dependencies
task setup
# Build in dev mode (fast iteration)
task build:dev

The setup command will install Rust, Python, Node.js, Go, Java, and Elixir tooling as needed.

Terminal window
# Build all crates
task build
# Build in dev mode (fast iteration)
task build:dev
# Build in release mode (optimized)
task build:release
Terminal window
# Run all tests
task test
# Run all checks (lint + test)
task check
Terminal window
# Format all code
task format
# Run all linters via prek
task lint
# Generate READMEs from templates
task generate:readme
Terminal window
# Update all dependencies
task update
# Clean all build artifacts
task clean

Each language binding has its own namespace:

Rust:

Terminal window
task rust:build
task rust:test
task rust:format
task rust:lint

Python:

Terminal window
task python:install
task python:test
task python:format
task python:lint

Node.js:

Terminal window
task node:build # Build NAPI-RS native module (release)
task node:build:dev # Build in debug mode
task node:test

Go:

Terminal window
task go:build # Build Go bindings (requires FFI)
task go:build:ffi # Build FFI static library for Go
task go:test
task go:format
task go:lint

Java:

Terminal window
task java:build:ffi # Build FFI shared library for Java
task java:test

Elixir:

Terminal window
task elixir:build # Compile (includes Rustler NIF)
task elixir:test
task elixir:deps

Ruby:

Terminal window
task ruby:build # Build Ruby native extension
task ruby:test # Run Ruby tests
task ruby:format # Format Ruby code
task ruby:lint # Lint Ruby code

WebAssembly:

Terminal window
task wasm:build # Build WASM package (web target)
task wasm:build:bundler # Build WASM package (bundler target)
task wasm:build:node # Build WASM package (Node.js target)
task wasm:test # Run WASM tests

C:

Terminal window
task c:build:ffi # Build FFI library for C tests
task c:e2e:build # Build C E2E tests
task c:e2e:test # Run C E2E tests
  1. Add a provider entry to schemas/providers.json:

    {
    "my-provider": {
    "base_url": "https://api.myprovider.com/v1",
    "auth_header": "Authorization",
    "auth_prefix": "Bearer",
    "model_prefixes": ["my-provider/"],
    "parameter_mappings": {}
    }
    }

    Fields:

    • base_url (required): Provider API base URL
    • auth_header (required): Header name for authentication
    • auth_prefix (optional): Prefix for the auth value (e.g. “Bearer”)
    • model_prefixes (required): Model name prefixes that route to this provider
    • parameter_mappings (optional): Map OpenAI parameter names to provider-specific names
  2. Regenerate types

    Terminal window
    task generate:types
  3. Build and test

    Terminal window
    task build:dev
    task test
  4. Regenerate E2E tests

    Terminal window
    task e2e:generate:all
    task test

E2E tests are generated from JSON fixtures in tools/e2e-generator/fixtures/ and produce runnable test suites for each language binding.

Terminal window
# Generate E2E tests for all languages
task e2e:generate:all
# Generate for a specific language
task e2e:generate:rust
task e2e:generate:python
task e2e:generate:go
task e2e:generate:java
task e2e:generate:elixir
task e2e:generate:ruby
task e2e:generate:c
# Run Rust E2E tests
task e2e:test:rust

Generated test files in e2e/ should not be edited directly – modify fixtures or the generator source instead.

Terminal window
# Show all available tasks
task --list
# Show all tasks including internal ones
task --list-all

The project uses prek for pre-commit hooks:

Terminal window
# Install hooks
prek install
prek install --hook-type commit-msg
# Run all hooks manually
prek run --all-files

We use conventional commits:

  • feat: add support for new-provider
  • fix: correct auth header injection
  • docs: update installation instructions
  • chore: update dependencies
  • test: add tests for streaming
  1. Create a feature branch

    Terminal window
    git checkout -b feat/add-provider-support
  2. Make your changes and run checks locally:

    Terminal window
    task check
  3. Commit and push

    Terminal window
    git commit -m "feat: add support for new provider"
    git push origin feat/add-provider-support
  4. Create a Pull Request – link any related issues and ensure CI passes.

Version is managed in Cargo.toml workspace and synced across all manifests:

Terminal window
task version:sync