Agent Guidance
May 27, 2026 · View on GitHub
Looking for instructions tailored to AI coding assistants?
Use CLAUDE.md. It is the canonical, maintained guide for all
agents (Claude, Cursor, ChatGPT, etc.) that interact with this repository.
PR Title Conventions for AI Assistants
This project uses Release Please for automated changelog generation. When creating PRs, use conventional commit format for PR titles:
Required Format
<type>[optional scope]: <description>
Supported Types
feat:New features (triggers MINOR version)fix:Bug fixes (triggers PATCH version)revert:Reverts of previous changes (triggers PATCH version)docs:Documentation changes (triggers PATCH version)chore:Maintenance, dependencies (triggers PATCH version)refactor:Code refactoring (triggers PATCH version)style:Formatting, linting (triggers PATCH version)test:Test changes (triggers PATCH version)perf:Performance improvements (triggers MINOR version)ci:CI/CD changes (triggers PATCH version)build:Build system changes (triggers PATCH version)
When reverting a change, use revert: (not the default Revert "..." subject)
so Release Please records it under the Reverts section of the changelog.
See CONTRIBUTING.md for the full revert workflow.
Breaking Changes
Add ! to indicate breaking changes (triggers MAJOR version):
feat!: remove deprecated APIfix!: change database schema
Examples
feat: add OAuth authentication support
fix: resolve Docker build failure
docs: update installation guide
chore: bump FastAPI dependency
feat!: remove deprecated authentication system
Why This Matters
- PR titles become commit messages after squash
- Every merged PR creates/updates a Release Please PR
- Release happens when the Release Please PR is merged
- Automatic changelog generation from PR titles
- Professional release notes for users
Release Workflow
- Merge any PR → Release Please creates/updates a release PR
- Review the release PR (version bump + changelog)
- Merge the release PR when ready to release
- Release Please publishes the release and triggers package publishing
See CONTRIBUTING.md for detailed guidelines.
Documentation Requirements
Every new feature or significant change must include documentation updates as part of the same PR, not as follow-up work. Update whichever of the following apply:
- Docs site (
vibetuner-docs/docs/) — the relevant page(s) for the feature area llms.txt(vibetuner-docs/docs/llms.txt) — concise feature entry in the Features sectionllms-full.txt(vibetuner-docs/docs/llms-full.txt) — detailed documentation with code examplesvibetuner-template/AGENTS.md— if the feature affects scaffolded projects (and the corresponding.claude/rules/file if applicable)
If you are unsure which docs to update, update all four. Omitting docs from a feature PR is a review blocker.
Testing Scaffold Changes from a Branch
When working on scaffold-related changes (template updates, CLI improvements), you can test the scaffolding CLI directly from a branch without publishing to PyPI:
# Test scaffold command from a specific branch
uvx git+https://github.com/alltuner/vibetuner@BRANCH_NAME#subdirectory=vibetuner-py scaffold new --help
# Create a test project using the branch
uvx git+https://github.com/alltuner/vibetuner@BRANCH_NAME#subdirectory=vibetuner-py scaffold new /tmp/test-project
The scaffold command also accepts a -b parameter to specify the branch dynamically:
# Specify branch with -b parameter (when available)
uvx git+https://github.com/alltuner/vibetuner#subdirectory=vibetuner-py scaffold new -b BRANCH_NAME /tmp/test-project
When to use this:
- Testing scaffold changes before merging a PR
- Verifying bug fixes in template or CLI
- Allowing others to test your changes before review
- CI/CD integration testing
Note: The .tmp/ directory at the root is gitignored. Use it for testing scaffold
commands if you have difficulty accessing external directories like /tmp:
# Test scaffolding in the repo's .tmp directory
uvx git+https://github.com/alltuner/vibetuner@BRANCH_NAME#subdirectory=vibetuner-py scaffold new ./.tmp/test-project
See vibetuner-docs/docs/development.md for complete development workflows.
Repository Justfile Commands
For developers working on the vibetuner repository itself, the root justfile provides commands for managing the monorepo.
Run just to see all available commands.
Dependencies
just update-all # Update all package dependencies (py, js, template, root)
just update-and-commit # Update all dependencies and commit changes
just update-py # Update Python dependencies in vibetuner-py
just update-js # Update JavaScript dependencies in vibetuner-js
just update-template # Update dependencies in vibetuner-template
just update-root # Update root scaffolding dependencies
just sync-jinja # Refresh vibetuner-jinja/templates from vibetuner-py
The sync-jinja recipe mirrors vibetuner-py/src/vibetuner/templates/frontend/
into vibetuner-jinja/templates/, the npm package that ships the framework's
core jinja templates so tailwind can @source them at frontend build time. The
same script runs as the package's prepare lifecycle hook, so workspace bun install and npm publish keep things in sync automatically — just sync-jinja
is just the manual entry point.
Documentation
just docs-serve # Serve documentation locally with live reload
just docs-build # Build documentation site
Code Quality
just format # Format all code (Python, Jinja, TOML, YAML)
just format-py # Format Python with ruff
just format-jinja # Format Jinja templates with djlint
just format-toml # Format TOML files with taplo
just format-yaml # Format YAML files with dprint
just lint # Run all linting checks
just lint-gh # Lint GitHub Actions workflows with actionlint
just lint-py # Lint Python with ruff
just lint-jinja # Lint Jinja with djlint
just lint-md # Lint markdown files
just lint-toml # Lint TOML with taplo
just lint-yaml # Lint YAML with dprint
just type-check # Type check at the repo root (template + tooling)
just type-check-py # Type check the vibetuner-py framework code with ty
Testing (vibetuner-py)
Dev dependencies (pytest, pytest-asyncio) are declared as an optional extra in
vibetuner-py/pyproject.toml. You must install them before running tests:
cd vibetuner-py
uv sync --extra dev
uv run python -m pytest tests/ # run all tests
uv run python -m pytest tests/unit/ # run unit tests only
Template Management
just update-frontend-templates # Sync frontend templates and commit changes
Beanie (MongoDB ODM)
Document.get() accepts plain strings
Beanie's Document.get() accepts Any for document_id, so wrapping IDs with
PydanticObjectId() is unnecessary:
# Correct - pass the string directly
doc = await MyDocument.get(some_id)
# Unnecessary - PydanticObjectId wrapping adds no value here
doc = await MyDocument.get(PydanticObjectId(some_id))
PydanticObjectId is still useful as a FastAPI path parameter type annotation (for request
validation) and in explicit query filters, but .get() handles the conversion internally.
Event hook methods must NOT start with an underscore
Beanie's init_actions() skips any method whose name starts with _ when registering
@before_event / @after_event hooks. A hook named _encrypt_on_save will silently
never fire. Always use public names:
# Correct - Beanie discovers and registers this hook
@before_event(Insert)
def encrypt_on_insert(self) -> None: ...
# Wrong - silently ignored by Beanie's action registry
@before_event(Insert)
def _encrypt_on_insert(self) -> None: ...
Ad-hoc collection access uses PyMongo, not Motor
The project uses pymongo (not motor). For direct collection access, use
get_pymongo_collection():
# Correct
collection = MyDocument.get_pymongo_collection()
# Wrong - motor was removed, this no longer exists
collection = MyDocument.get_motor_collection() # AttributeError
Logging
All code in vibetuner-py/src/vibetuner/ must use the project's Loguru-based logger:
from vibetuner.logging import logger
Do not use import logging or logging.getLogger(...) directly. The only exception is
vibetuner/logging.py itself, which defines the logging facility and necessarily imports the
stdlib logging module.
The InterceptHandler in vibetuner/logging.py routes stdlib logging through Loguru, so
third-party libraries still work. But framework code should always use the Loguru logger
directly for consistent formatting, request-ID injection, and log-level control.
Markdown Line Length
This project enforces a 120 character line limit for markdown files using rumdl.
When editing markdown files:
- Keep lines under 120 characters
- Break long lines at natural points (commas, list items, sentence boundaries)
- Indent continuation lines consistently with their parent items
- Pre-commit hooks will catch violations before commit
Example of properly wrapped markdown:
1. Stage all relevant changes:
- **IMPORTANT**: NEVER stage release-related files: `.release-please-manifest.json`,
`CHANGELOG.md`, version changes in `pyproject.toml` or `package.json`
- Use `git add` with explicit file paths for each file you want to commit