Context
When working with vibetuner projects, AI agents frequently need to run ad-hoc database operations (backfills, migrations, data fixes). The current documentation (CLAUDE.md / llms.txt) doesn't cover how to connect to the database for one-off scripts, leading to trial-and-error.
Learnings from a real session
-
The MongoDB driver is pymongo (async), not motor. Agents default to trying from motor.motor_asyncio import AsyncIOMotorClient which fails. The correct import is:
from pymongo import AsyncMongoClient
-
Beanie uses get_pymongo_collection(), not get_motor_collection(). Even Beanie's own error hint suggests the correct method, but agents waste a round-trip discovering this.
-
Settings access pattern: The correct way to get DB connection info is:
from vibetuner.config import settings
client = AsyncMongoClient(str(settings.mongodb_url))
db = client[settings.project.project_slug]
-
Seed data had status=None instead of the model default "draft", so queries filtering on status == "draft" missed those documents. This is a common gotcha when backfilling new fields — existing documents may have None for fields that have defaults in the Pydantic model.
Suggested documentation addition
A section in CLAUDE.md (and/or llms.txt) like:
### Ad-hoc Database Operations
For one-off database scripts (backfills, migrations, data fixes):
\```python
import asyncio
from beanie import init_beanie
from pymongo import AsyncMongoClient
from vibetuner.config import settings
async def run():
client = AsyncMongoClient(str(settings.mongodb_url))
db = client[settings.project.project_slug]
await init_beanie(database=db, document_models=[YourModel])
# Use Beanie queries or raw pymongo:
col = YourModel.get_pymongo_collection()
result = await col.update_many(filter, update)
asyncio.run(run())
\```
**Important**: This project uses `pymongo` (not `motor`). Use `AsyncMongoClient`
from `pymongo`, and `get_pymongo_collection()` on Beanie documents.
**Gotcha**: Existing documents may have `None` for fields that have defaults in
Pydantic models. When querying by such fields, include `None` in your filter
(e.g., `{"status": {"$in": [None, "draft"]}}`).
This would save agents multiple failed attempts per session when doing routine database work.
Context
When working with vibetuner projects, AI agents frequently need to run ad-hoc database operations (backfills, migrations, data fixes). The current documentation (
CLAUDE.md/llms.txt) doesn't cover how to connect to the database for one-off scripts, leading to trial-and-error.Learnings from a real session
The MongoDB driver is
pymongo(async), notmotor. Agents default to tryingfrom motor.motor_asyncio import AsyncIOMotorClientwhich fails. The correct import is:Beanie uses
get_pymongo_collection(), notget_motor_collection(). Even Beanie's own error hint suggests the correct method, but agents waste a round-trip discovering this.Settings access pattern: The correct way to get DB connection info is:
Seed data had
status=Noneinstead of the model default"draft", so queries filtering onstatus == "draft"missed those documents. This is a common gotcha when backfilling new fields — existing documents may haveNonefor fields that have defaults in the Pydantic model.Suggested documentation addition
A section in
CLAUDE.md(and/orllms.txt) like:This would save agents multiple failed attempts per session when doing routine database work.