CLAUDE.md · diff
git:20260903.43ad496 to git:20260912.398e9ef
2 added, 1 removed. Audit A to A.
> **Audience: Pixeltable contributors.** If you're building an *application* with Pixeltable, use the [Agent Skill](https://github.com/pixeltable/pixeltable-skill) instead (`npx skills add pixeltable/pixeltable-skill`).
# CLAUDE.md
Instructions for AI coding agents working with the Pixeltable codebase.
## Protected Configuration
Never change `integrations.telemetry.enabled` in `docs/release/docs.json`. It must remain set to `true` in every pull request.
## Project Overview
Pixeltable is an open-source Python library providing declarative data infrastructure for building multimodal AI applications. It enables incremental storage, transformation, indexing, retrieval, and orchestration of data across images, video, audio, and documents.
**Key concepts:**
- **Tables**: Store structured and unstructured data with native multimodal column types (`pxt.Image`, `pxt.Video`, `pxt.Audio`, `pxt.Document`)
- **Computed Columns**: Declaratively define transformations that run automatically on new/updated data
- **Views**: Virtual tables with iterators for efficient data processing (e.g., document chunking, video frame extraction)
- **Embedding Indexes**: Built-in vector search with automatic index maintenance
- **UDFs**: User-defined functions with `@pxt.udf` and `@pxt.query` decorators
- **AI Integrations**: Built-in functions for OpenAI, Anthropic, Hugging Face, and many more
**Documentation**: https://docs.pixeltable.com/
**SDK Reference**: https://docs.pixeltable.com/sdk/latest/pixeltable
## Repository Structure
```
pixeltable/
├── pixeltable/ # Main library source code
│ ├── catalog/ # Table, View, Column metadata and operations
│ ├── exec/ # Query execution engine
│ ├── exprs/ # Expression types and operators
│ ├── func/ # UDF/query function infrastructure
│ ├── functions/ # Built-in AI provider integrations (openai, anthropic, etc.)
│ ├── index/ # Embedding index implementations
│ ├── io/ # Import/export (CSV, Parquet, Hugging Face, etc.)
│ ├── iterators/ # View iterators (DocumentSplitter, FrameIterator, etc.)
│ ├── metadata/ # Schema migration and persistence
│ ├── share/ # Data sharing (publish/replicate)
│ └── utils/ # Utilities
├── tests/ # Test suite
│ ├── functions/ # Tests for AI integrations
│ ├── io/ # Tests for import/export
│ └── data/ # Test fixtures (images, videos, documents)
├── docs/
│ ├── release/ # Mintlify documentation source (notebooks, MDX)
│ ├── _guidelines/ # Documentation style guides
│ └── sample-apps/ # Older showcases; examples live in pixeltable-starter-kit
└── tool/ # Development utilities
```
## Setup Commands
**Prerequisites:** Miniforge with a dedicated environment (not `base`)
```bash
# Create and activate conda environment
mamba create --name pxt python=3.11
conda activate pxt
# Install development dependencies
make install
# Run tests (excludes expensive/remote API tests by default)
make test
# Run full test suite including notebooks
make fulltest
# Run minimal test suite for quick checks
make slimtest
```
## Development Workflow
### Code Style
- **Line length**: 120 characters
- **Quotes**: Single quotes (`'`) preferred
- **Formatter**: ruff (`make format`)
- **Type hints**: Required for all functions (mypy strict mode)
- **Imports**: Group by standard library → third-party → pixeltable
```bash
# Format code
make format
# Run static checks (mypy + ruff)
make check
# Individual checks
make typecheck # mypy
make lint # ruff check
make formatcheck # ruff format --check
```
### Testing
```bash
# Run pytest (excludes expensive/remote_api tests)
make pytest
# Run full pytest including expensive tests
make fullpytest
# Run specific test file
pytest tests/test_table.py -v
# Run tests matching a pattern
pytest -k "test_insert" -v
# Run with remote API tests (requires credentials)
pytest -m "remote_api" tests/functions/test_openai.py
```
**Test markers:**
- `@pytest.mark.expensive` - Long-running tests
- `@pytest.mark.remote_api` - Tests calling external APIs
### Required After Every Code Change
After every code change, before reporting it done:
1. `make format`: auto-formats code.
2. `make check`: mypy + ruff static checks; both must pass.
3. `git add` any new source file, then review the whole change with `git diff HEAD` (no pathspec: source
and tests), reading every comment, docstring, and string you added. A diff narrowed to one file does not
count, and an unstaged new file does not appear in it. A comment must describe only the code at hand
(never a caller's intent or a called function's internals) and must not state behavior you have not
verified.
4. Delete before rewording: cover each comment and read only the identifier, the signature, and the code
below it. If those carry the same fact, delete the comment rather than improving it. A docstring that
paraphrases the name, an "or None if ..." for a `| None` annotation, and a fact already stated elsewhere
all go. Keep what the reader cannot recover: a constraint a callee imposes, the reason for a surprising
choice, an invariant that would silently break.
5. Check the prose that survived for straight word order, per `feedback_simple_direct_prose.md`: no
preposition stranded at the end of a clause, no noun-phrase pileup ("the X a Y is Z to"), no fused
emphatic ("X is what makes Y work" -> "X makes Y work"). Where a plainer phrase says the same thing, use
it. Fix every violation from steps 3 to 5 before proceeding.
Skip only if explicitly directed or if the environment makes it impossible.
### Creating a Pull Request
1. Create a branch from `main`
2. Make changes and add tests in `tests/`
3. Run `make format` and `make check` (see above)
4. Run `make test` to run the test suite
5. Push and create PR via GitHub
## Code Conventions
### Adding a New UDF
UDFs go in `pixeltable/functions/`. Each provider has its own module (e.g., `openai.py`, `anthropic.py`).
```python
# pixeltable/functions/my_provider.py
import pixeltable as pxt
@pxt.udf
def my_function(input_text: str, model: str = 'default-model') -> str:
"""
Brief description of what this function does.
Args:
input_text: The input text to process.
model: The model to use for processing.
Returns:
The processed output text.
Example:
>>> t.add_computed_column(result=my_function(t.text, model='advanced'))
"""
# Implementation
pass
```
**Important patterns:**
- Use `@pxt.udf` for scalar functions, `@pxt.uda` for aggregates
- Use `.using()` for model parameterization in embedding functions
- Add tests in `tests/functions/test_my_provider.py`
### Adding a New Iterator
Iterators go in `pixeltable/iterators/`. They split rows into multiple output rows.
```python
# pixeltable/iterators/my_iterator.py
from pixeltable.iterators import ComponentIterator
import pixeltable.type_system as ts
class MyIterator(ComponentIterator):
"""Iterator that splits X into multiple rows."""
def __init__(self, input_data: SomeType):
# Initialize iteration state
pass
def __next__(self) -> dict[str, Any]:
# Return next row as dict
pass
def close(self) -> None:
pass
@classmethod
def input_schema(cls) -> dict[str, ts.ColumnType]:
return {'input_data': ts.SomeType()}
@classmethod
def output_schema(cls, *args, **kwargs) -> tuple[dict[str, ts.ColumnType], list[str]]:
return {'output_field': ts.SomeType()}, []
```
### Working with Tables
Application schema is a `TableModel` class in `app.py`. `pxt schema update app.py my_app` creates those tables. Put `FastAPIRouter` routes in that same `app.py`. In tests, notebooks, and a REPL, keep using `pxt.create_table()`; do not require a project file there.
```python
import pixeltable as pxt
import pixeltable.functions as pxtf
from pixeltable.serving import FastAPIRouter
TableModel = pxt.model_base()
class Docs(TableModel, name='docs'):
+ doc_id = pxt.Column(value=pxtf.uuid.uuid7(), primary_key=True)
title: pxt.String
body: pxt.String | None
title_upper = pxtf.string.upper(title)
ingest = FastAPIRouter(name='ingest')
ingest.add_insert_route(
- Docs, path='/docs', inputs=[Docs.title, Docs.body], outputs=[Docs.title, Docs.title_upper]
+ Docs, path='/docs', inputs=[Docs.title, Docs.body], outputs=[Docs.doc_id, Docs.title, Docs.title_upper]
)
```
```bash
pxt schema update app.py my_app
pxt service update app.py my_app
```
After `pxt schema update`, open the table with `t = pxt.get_table('my_app.docs')`, then `t.insert()` / `.select()` / `.collect()`. On a `TableModel`, put indexes in `__indexes__`. Do not call `add_embedding_index()` in application code that you later create with `pxt schema update`.
Tests and notebooks (not app files):
```python
import pixeltable as pxt
t = pxt.create_table('my_dir.my_table', {
'text': pxt.String,
'image': pxt.Image,
'metadata': pxt.Json,
})
t.add_computed_column(embedding=some_embedding_fn(t.text))
t.add_embedding_index('text', embedding=embed_fn)
t.insert([{'text': 'hello', 'image': 'path/to/image.jpg'}])
```
### Error Handling
- Use `pixeltable.exceptions` for custom exceptions
- Validate inputs early and provide clear error messages
- Use `exn.Error` for user-facing errors
## Documentation
### Notebooks
Documentation notebooks are in `docs/release/`. Follow `docs/_guidelines/GUIDELINES_FOR_NOTEBOOKS.md`:
- Start with YAML frontmatter in a **Raw cell** (not Markdown)
- No H1 headers in markdown (title comes from frontmatter)
- Use `##` for main sections, `###` for subsections
- Clear outputs before committing unless output is instructive
- Use `raw.githubusercontent.com` for GitHub raw links
### Docstrings
Follow `docs/_guidelines/GUIDELINES_FOR_DOCSTRINGS.md`:
- Code examples must use `>>>` prompts, not fenced code blocks
- Backticks must be properly paired
- HTML tags must be self-closing
- When describing what a function does, focus on the behavior of the function itself, not its callers
### Code Comments
- Keep code comments succinct; avoid unnecessarily verbose comments.
- Always use parens to denote functions: in code comments, it's `my_func()`, not `my_func`.
### Building Docs
```bash
# Build documentation
make docs
# Serve locally for development
make docs-serve
# Deploy to staging
make docs-deploy TARGET=stage
```
### Local Dashboard UI
Before changing `dashboard/` or dashboard-facing APIs in `pixeltable_cli/server/`, read [`dashboard/DESIGN.md`](dashboard/DESIGN.md) (required) and [`dashboard/ARCHITECTURE.md`](dashboard/ARCHITECTURE.md). Follow DESIGN.md; justify any visual departure explicitly.
## Testing Against Remote APIs
For tests that call external APIs (OpenAI, Anthropic, etc.):
1. Set appropriate environment variables (e.g., `OPENAI_API_KEY`)
2. Run with the `remote_api` marker: `pytest -m "remote_api" tests/functions/test_openai.py`
3. These tests are excluded from CI by default
## Database and Storage
- Pixeltable uses embedded PostgreSQL at `~/.pixeltable/pgdata`
- Generated media stored at `~/.pixeltable/media`
- File cache at `~/.pixeltable/file_cache`
- **Never directly modify** files in `~/.pixeltable`; use the SDK
To reset the database for testing:
```bash
scripts/drop-pxt-db.sh
```
## Common Patterns
### Idempotent Operations
Use `if_exists='ignore'` or `if_not_exists=True` for idempotent schema operations:
```python
pxt.create_dir('my_dir', if_exists='ignore')
pxt.create_table('my_dir.table', schema, if_exists='ignore')
t.add_computed_column(col=expr, if_exists='ignore')
t.add_embedding_index('col', embedding=fn, if_not_exists=True)
```
### Query Functions
Encapsulate complex queries as reusable functions:
```python
@pxt.query
def search_documents(query_text: str, limit: int = 10):
sim = docs.text.similarity(string=query_text)
return docs.order_by(sim, asc=False).limit(limit).select(docs.text, sim)
```
### Handling Nullable Columns
Check for null values when processing data:
```python
@pxt.udf
def safe_process(value: Optional[str]) -> str:
if value is None:
return ''
return process(value)
```
## Key Files Reference
| File | Purpose |
|------|---------|
| `pixeltable/__init__.py` | Public API exports |
| `pixeltable/catalog/table.py` | Table class implementation |
| `pixeltable/catalog/view.py` | View class implementation |
| `pixeltable/func/udf.py` | UDF decorator implementation |
| `pixeltable/functions/` | AI provider integrations |
| `pixeltable/io/` | Import/export functionality |
| `pixeltable_cli/` | CLI + daemon (serves dashboard API and static SPA) |
| `dashboard/` | Local web UI frontend (React/Vite); see `dashboard/DESIGN.md` |
| `dashboard/DESIGN.md` | Dashboard visual/UX source of truth (required for UI changes) |
| `dashboard/ARCHITECTURE.md` | Dashboard stack and API map |
| `pyproject.toml` | Dependencies and tool config |
| `Makefile` | Build and test commands |