Skip to content

Commit 7fbc1f7

Browse files
committed
AGENTS.md
1 parent c9993c0 commit 7fbc1f7

2 files changed

Lines changed: 86 additions & 85 deletions

File tree

AGENTS.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# CLAUDE.md
2+
3+
## Project Overview
4+
5+
duckdb.mojo provides Mojo bindings for DuckDB with two modes:
6+
1. **Client API** - Query DuckDB from Mojo, register scalar/aggregate/table UDFs, process results with SIMD vectorization
7+
2. **Extension development** (experimental) - Build DuckDB extensions as shared libraries in Mojo
8+
9+
## Tech Stack
10+
11+
- **Language:** Mojo (stable releases, pinned in pixi.toml)
12+
- **Database:** DuckDB 1.5 (C API via auto-generated FFI bindings)
13+
- **Package manager:** Pixi (conda-based, config in pixi.toml)
14+
- **CI:** GitHub Actions (test.yml - runs on linux-64, linux-aarch64, osx-arm64)
15+
16+
## Project Structure
17+
18+
- `duckdb/` - Main library source (the `duckdb` Mojo package)
19+
- `_libduckdb.mojo` - Auto-generated low-level C API bindings (do not edit manually)
20+
- `connection.mojo`, `database.mojo`, `result.mojo` - Core client API
21+
- `scalar_function.mojo`, `aggregate_function.mojo`, `table_function.mojo` - UDF registration
22+
- `extension.mojo`, `api_level.mojo` - Extension development support
23+
- `chunk.mojo`, `vector.mojo`, `value.mojo`, `logical_type.mojo` - Data types
24+
- `test/` - Test files (one per module, named `test_*.mojo`)
25+
- `demo-extension/` - Working example DuckDB extension in Mojo
26+
- `test-extension/` - Extension used for testing
27+
- `benchmark/` - Performance benchmarks
28+
- `scripts/` - Code generation and build helpers
29+
- `packages/` - Sub-packages (duckdb-from-source, operator-replacement)
30+
31+
## Development Commands
32+
33+
All commands run inside `pixi shell` or via `pixi run`:
34+
35+
```shell
36+
pixi shell # Enter dev environment
37+
pixi run test # Run all tests (library + extensions)
38+
pixi run test-library # Run library tests only
39+
pixi run mojo run example.mojo # Run example
40+
pixi run generate-api # Regenerate C API bindings from DuckDB source
41+
pixi run check-generated-api # Fail if _libduckdb.mojo is out of sync with DuckDB
42+
pixi build # Build conda package
43+
```
44+
45+
## Testing
46+
47+
- Tests are individual Mojo files in `test/`, one per module
48+
- Run all: `pixi run test` (runs test-library + test-demo-extension + test-extension)
49+
- Run single: `pixi run mojo run test/test_connection.mojo`
50+
- Tests use assertions (no test framework) - a non-zero exit code indicates failure
51+
52+
## Key Patterns
53+
54+
- The `Connection` type is parameterized with `ApiLevel` (CLIENT, EXT_STABLE, EXT_UNSTABLE) to gate API access at compile time
55+
- `_libduckdb.mojo` is auto-generated - regenerate with `pixi run generate-api` after bumping DuckDB version. CI runs `check-generated-api` (a dedicated job in `test.yml`) to fail the build if the committed bindings are stale, so a forgotten regeneration can't slip into main.
56+
- Extensions use the DuckDB Extension C API with stable/unstable split
57+
58+
## FFI Struct ABI Workaround
59+
60+
Mojo's `abi("C")` lowering on Linux x86_64 has a remaining miscompilation for >16-byte by-value struct arguments when the struct type lacks `TrivialRegisterPassable`. As a workaround, the generator emits `duckdb_result` with `TrivialRegisterPassable` in its trait list — this routes it through the working ABI path. The trait isn't accurate semantically (a 48-byte struct can't actually fit in registers under System V x86_64); it's purely a marker for selecting Mojo's correct lowering. Track upstream resolution at https://github.com/modular/modular/issues/6511 (the fix landed for the `TrivialRegisterPassable` case; a follow-up is needed for non-TRP structs).
61+
62+
## Updating Mojo Nightly
63+
64+
The Mojo compiler version is pinned in `pixi.toml` (currently `1.0.0b2.dev2026053106` from the `https://conda.modular.com/max-nightly/` channel, set in `package.host-dependencies`, `package.build-dependencies`, the `[dependencies]` `mojo`, and the `operator-replacement` feature's `mojo`) **and** in `conda.recipe/recipe.yaml` (`requirements.build`/`host`/`run`). To update:
65+
66+
1. Check available versions: query `https://conda.modular.com/max-nightly/osx-arm64/repodata.json` (or `linux-64`/`linux-aarch64`) for `mojo-compiler` packages
67+
2. Update the version pin in `pixi.toml` (both `host-dependencies` and `build-dependencies`)
68+
3. Update the same pin in `conda.recipe/recipe.yaml` and `conda.recipe/recipe.local.yaml` (all three of `build`/`host`/`run`) — otherwise `pixi build` and the published conda package will disagree
69+
4. Run `pixi install` to update the lockfile
70+
5. Run `pixi run test-library` to verify compatibility
71+
6. Nightly builds can have breaking changes — if the latest fails, try earlier nightlies
72+
73+
## Packaging / publishing
74+
75+
Two independent paths build a conda package of the bindings, and they must be kept in sync (see the pin checklist above):
76+
77+
- **`pixi build`** — the `[package]` block + `pixi-build-mojo` backend in `pixi.toml`. The backend infers the build steps (no recipe). Used for local builds and for consuming duckdb.mojo as a source dependency from other Pixi workspaces.
78+
- **`conda.recipe/recipe.yaml`** (rattler-build) — an explicit recipe. This is what gets submitted to the [modular-community](https://github.com/modular/modular-community) channel, whose CI runs `rattler-build` on it. Key points: the `run` dependency pins `mojo-compiler` **exactly** (a precompiled `.mojoc` only loads under the exact compiler it was built with — `pin_compatible` would let a newer nightly fail at import); `libduckdb` is a `run` dependency (the bindings `dlopen` it). Verify locally with `conda.recipe/recipe.local.yaml`, which builds from the working tree instead of a pushed git SHA. Before submitting a release, set `source.rev` in `recipe.yaml` to the full release commit SHA.
79+
80+
The sub-packages in `packages/` use a third mechanism (the `pixi-build-rattler-build` backend, which runs rattler-build on their own `recipe.yaml` via `pixi build`) — unrelated to publishing the `duckdb-mojo` package.
81+
82+
## Environments
83+
84+
- **default** - Standard dev environment with precompiled libduckdb from conda-forge
85+
- **full** - Extended environment with operator-replacement feature (builds DuckDB from source)

CLAUDE.md

Lines changed: 0 additions & 85 deletions
This file was deleted.

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
AGENTS.md

0 commit comments

Comments
 (0)