chameleon-rs chameleon-rs chameleon-rs
  • User Guide
  • Language Reference
  • Recipes
  • API Reference

Skills

A skill is a package of structured files that teaches an AI coding agent how to work with a specific tool or framework. The skill below was generated by Great Docs from this project’s documentation. Install it in your agent and it will be able to run commands, edit configuration, write content, and troubleshoot problems without step-by-step guidance from you.

Any agent — install with npx:

npx skills add https://mkennedy.codes/docs/chameleon-rs/

Codex / OpenCode

Tell the agent:
Fetch the skill file at https://mkennedy.codes/docs/chameleon-rs/skill.md and follow the instructions.

Manual — download the skill file:

curl -O https://mkennedy.codes/docs/chameleon-rs/skill.md

Or browse the SKILL.md file.

SKILL.md

---
name: chameleon-rs
description: >
  A Rust implementation of the Chameleon page template engine, compatible with Chameleon's syntax and API. Use when writing Python code that uses the chameleon_rs package.
license: LicenseRef-Chameleon
compatibility: Requires Python >=3.12.
---

# chameleon-rs

A Rust implementation of the Chameleon page template engine, compatible with Chameleon's syntax and API.

## Installation

```bash
pip install chameleon-rs
```

## When to use what

| Need | Use |
|------|-----|
| Run an existing Chameleon app on chameleon-rs with no code changes | `chameleon_rs.compat.install() at the top of the entry point` |
| Render a template string | `chameleon_rs.PageTemplate(source)(**model)` |
| Load templates by name from folders | `chameleon_rs.PageTemplateLoader([folder])['page.pt'](**model)` |
| Insert a reusable HTML fragment | `${render_partial('shared/fragment.pt', key=value)}` |
| Get a rendered fragment as a string from Python (HTMX, email, tests) | `chameleon_rs.render_partial(path, **model).html_text` |
| Render Chameleon templates from Flask or Quart views | `chameleon_rs.flask: configure(folder), then @template('page.pt') on the view` |

## API overview

### Templates

Compile and render templates from strings, files and folders.

- `PageTemplate`: Constructor for the page template language, rendered by the Rust VM
- `PageTemplateFile`: File-based constructor: the template is read from ``filename`` (or, with
- `PageTextTemplate`: Text-based template class: only ``${...}`` interpolation, no markup, nothing escaped
- `PageTextTemplateFile`: File-based text template. Rendering returns ``bytes``, encoded with the template's
- `PageTemplateLoader`

### PageTemplate Methods

Methods for the PageTemplate class

- `PageTemplate.__getitem__`
- `PageTemplate.builtins`
- `PageTemplate.parse`
- `PageTemplate.include`
- `PageTemplate.render`
- `PageTemplate.render_async`
- `PageTemplate.digest`

### Configuration

Process-wide settings for templates loaded by name.

- `configure`: Configures chameleon-rs for the whole process: where templates loaded by name live, for
- `core_version`: Version of the Rust core, for bug reports and for checking which build is loaded

### Partials

Render one template inside another. Also chameleon_partials' API.

- `render_partial`: The ``render_partial`` callable: ``chameleon_rs.render_partial`` (no calling template)
- `partials.register_extensions`
- `partials.extend_model`
- `partials.clear`
- `partials.PartialRenderer`
- `partials.HTML`
- `partials.PartialsException`

### Flask and Quart

chameleon-flask's API, built in. Imports Flask only when imported itself.

- `flask.configure`
- `flask.global_init`
- `flask.template`
- `flask.render`
- `flask.response`
- `flask.not_found`
- `flask.error`
- `flask.clear`

### Errors and web helpers

Exceptions, and the pieces shared by the framework integrations.

- `TemplateError`: An error raised by Chameleon
- `web.TemplateError`
- `web.ErrorPage`
- `web.NotFound`
- `web.model_of`

### Compatibility

Make `import chameleon` resolve to chameleon-rs, or check both engines side by side.

- `compat.install`
- `shadow.install`
- `shadow.uninstall`
- `shadow.ShadowDifference`

## Gotchas

1. chameleon_rs.compat.install() must run before anything imports chameleon, chameleon_partials or chameleon_flask; a module already imported keeps stock Chameleon's objects.
2. render_partial looks in the configured template folder, then on the calling template's search path and in its folder and each folder above it. chameleon_rs.configure(partial_search='registered') restores chameleon_partials' lookup (configured folder only).
3. render_partial is a builtin in every template; you don't need extend_model() or a BeforeRender subscriber (both still work).
4. configure() applies on every call (there is no cache_init); the first call must give template_folder.
5. template.source does not exist as Python code: with keep_source=True it is a dump of the compiled program.
6. Custom expression types that return Python AST work through a bridge at fallback speed; types that depend on Chameleon's compiler internals are not supported.

## Best practices

- Call chameleon_rs.configure(template_folder=..., auto_reload=dev_mode) once at startup, before the first render.
- To switch an existing app, add `import chameleon_rs.compat; chameleon_rs.compat.install()` as the first lines of the entry point, and leave the rest of the code unchanged.
- Prefer ${render_partial('shared/card.pt', item=item)} as a whole expression: it renders as a native frame of the page, with no Python call.
- Build template folder paths with (Path(__file__).parent / 'templates').as_posix().
- In tests, reset with chameleon_rs.partials.clear() (or chameleon_rs.flask.clear()) between configurations.

## What chameleon-rs is

A Rust implementation of the Chameleon page template engine (`import chameleon_rs`, PyPI
`chameleon-rs`). Same template language (TAL, METAL, i18n, `${...}`), same Python API, the
same output byte for byte, and faster rendering. It has no runtime dependencies, and stock
Chameleon doesn't need to be installed.

## Switching an existing Chameleon app

Add these lines at the very top of the app's entry point, above every other import:

```python
import chameleon_rs.compat

chameleon_rs.compat.install()
```

After that, `import chameleon`, `import chameleon_partials` and `import chameleon_flask` give
chameleon-rs's modules. Don't change templates or other code. If `chameleon` was imported
before `install()`, objects taken from it stay stock Chameleon objects, so move the call
earlier.

## A new app

```python
from pathlib import Path

import chameleon_rs
from chameleon_rs import PageTemplateLoader

folder = (Path(__file__).parent / 'templates').as_posix()
chameleon_rs.configure(template_folder=folder, auto_reload=dev_mode)  # once, at startup
templates = PageTemplateLoader([folder])

html = templates['home/index.pt'](title='Home', videos=videos)
```

Every template has `render_partial` built in, with no `extend_model` and no `BeforeRender`
subscriber:

```html
<div tal:repeat="video videos">
  ${render_partial('shared/video_card.pt', video=video)}
</div>
```

A partial sees only the keyword arguments passed to it. A path is looked for in the
configured folder, then next to the calling template and in the folders above it.

## Flask and Quart

```python
import chameleon_rs.flask as chameleon_flask

chameleon_flask.configure(template_folder=folder, auto_reload=dev_mode)

@app.get('/')
@chameleon_flask.template('home/index.pt')
def index():
    return {'message': 'Hello'}   # a dict, mapping, dataclass or Pydantic model
```

`chameleon_flask.not_found()` and `chameleon_flask.error(template, status_code)` end a
decorated view with an error page. `chameleon_rs.render_partial(path, **model).html_text`
returns a fragment as a string, for HTMX responses.

## Known differences from Chameleon

- `template.source` is a dump of the compiled program, not Python code.
- Custom expression types that return Python AST work through a bridge, at the speed of an
  ordinary Python call.
- `CHAMELEON_CACHE` writes nothing to disk; compiling is fast enough not to need it.
- `chameleon.nodes`, `chameleon.program`, `chameleon.zpt.program` and `chameleon.benchmark`
  don't exist.


## Resources

- [Full documentation](https://mkennedy.codes/docs/chameleon-rs/)
- [llms.txt](llms.txt) — Indexed API reference for LLMs
- [llms-full.txt](llms-full.txt) — Comprehensive documentation for LLMs
- [Source code](https://github.com/mikeckennedy/chameleon-rust)

Developed by Michael Kennedy.
Site created with Great Docs.