AI setup
How Zeno configures Cursor and other AI coding assistants
Zeno is set up for AI-assisted development with Cursor and other AI coding tools.
AI assistants write better code when they know your project's conventions. Zeno ships AGENTS.md files that describe them, and a Cursor hook that runs Ultracite on every file the agent edits, so AI-generated code meets the same lint and format rules as hand-written code.
AGENTS.md
Cursor and other AI assistants pick up the root AGENTS.md on their own. It covers:
- The project overview and the folder map, with a link to each package's own
AGENTS.md - Which code ships through the shadcn registry and which ships on npm
- Development commands and their catches
- Formatting and testing rules
- Rules for Supabase, agent skills and secrets
Packages with their own traps have an AGENTS.md too. Not every tool loads those nested files, so the root file tells the agent to read each AGENTS.md between a folder and the root before it changes code there.
Cursor configuration
The .cursor/ directory contains Cursor-specific configuration:
.cursor/
├── rules/
│ └── ultracite.mdc # Code quality standards (applied to *.ts, *.tsx, *.js, *.jsx)
└── hooks.json # Auto-fix after file editsRules
The Ultracite rule is scoped to source files and automatically loaded when working with matching files. It covers type safety, modern JS/TS patterns, React best practices, error handling, security, and performance.
Hooks
.cursor/hooks.json registers an afterFileEdit hook that runs Ultracite after every file edit the Cursor agent makes:
{
"hooks": {
"afterFileEdit": [
{
"command": "pnpm dlx ultracite fix"
}
]
}
}The hook formats and lint-fixes the agent's edits before you review them, so a file on disk can differ from what the agent just wrote.
AI-friendly patterns
Zeno follows these patterns, which give an AI assistant more context to work from:
Explicit types
Use interfaces for props and function signatures so AI understands the contract:
interface UserProps {
id: string
name: string
email: string
}
function UserCard({ id, name, email }: UserProps) {
// ...
}Descriptive names
Start boolean names with an auxiliary verb such as is or has, so the name says what the value means:
// Good
const isUserAuthenticated = checkAuth()
const hasAdminPermissions = user.role === "admin"
// Avoid
const auth = checkAuth()
const admin = user.role === "admin"Co-located types
Define a type next to the code that uses it, so an assistant reading that code sees both:
interface CreateUserInput {
name: string
email: string
}
async function createUser(input: CreateUserInput) {
// AI has full context
}LLM documentation
The Zeno docs serve Markdown for LLMs, through Fumadocs:
- Any doc page is available as Markdown at
/docs/<path>.mdx(for example/docs/foundation/getting-started/installation.mdx)
An AI assistant can fetch these URLs to read the docs.