Bullets without a prefix are mandatory; Recommended: / Preferred: mark soft guidance.
- Start with the simplest solution that works. Add complexity only when there is a proven need — not because something "might" be useful.
Applies to: app/**
- Follow Feature-Sliced Design (FSD): features in
app/features/, entities inapp/entities/, shared code inapp/shared/.- Server-only code within a slice lives in a dedicated
server.tsfile at the slice root, separate from client code.
- Server-only code within a slice lives in a dedicated
- Prefer functional style. Use classes only to scope domain-specific logic (e.g., IDL interpreters, program executors).
Applies to: app/**/*.{ts,tsx,mts,mjs,cjs,js}
- Recommended: organize files top-down — exported/public API at the top, auxiliary helpers toward the bottom.
- Use path aliases (
@entities/,@features/,@shared/,@utils/,@providers/,@validators/) over relative imports. - Use object destructuring for function parameters when there are 3+ arguments or 2+ optional arguments.
- Recommended: argument ordering — stable/context arguments first (cluster, connection, config), data arguments in the middle, arguments with default values last.
Applies to: app/**/*.{ts,tsx}
- Add a clarification comment when a decision might look wrong or surprising to a future reader (e.g. using an index key when a natural key exists, choosing a seemingly suboptimal approach for a non-obvious reason). Explain why, not what.
Applies to: app/**/*.tsx
- Use
class-variance-authority(CVA) for component variants — not conditional class logic or CSS overrides. - Recommended: name stateless, hook-free UI components with a
Baseprefix (e.g.,BaseSearch,BaseTransactionCard). When using theBaseprefix, pair the component with a Storybook story.
Applies to: **/*.stories.{ts,tsx}
- Do not use unnecessary decorators. Do not create wrappers that aren't used in the app.
- Infer story args from the component signature — do not remap props.
- Do not use
centeredlayout — real component edges must be visible.
Applies to: app/**/*.{ts,tsx}
- Use
superstructfor runtime validation of external data (API responses, URL params, user input). - Use the
Loggerabstraction (Logger.error,Logger.warn,Logger.info) instead of direct Sentry imports. Import Sentry utilities from@/app/shared/lib/sentry, not from@sentry/nextjs. - Preferred: use
@solana/kitfor new functionality and when refactoring existing code.
Applies to: app/features/**, app/entities/**, app/shared/**
- Cover features, entities, and shared modules with unit tests when adding or modifying code.
- The CI pipeline runs
pnpm format:ci→pnpm lint→pnpm openspec:validate→pnpm build→pnpm test:ci. These checks are mandatory — fix violations, never bypass them (no--no-verify, no skipping, no disabling rules to silence output). The local hooks below are a developer convenience to surface failures before push; the checks themselves are not optional. Enable withgit config core.hooksPath .githooks:pre-commit— runspretty:format,eslint:lint, andtest:changedscoped to staged files.pre-push— runs the full pipeline (format, lint, openspec:validate, build, test).
- Optionally, use
actto run GitHub Actions workflows locally before pushing.
Non-trivial design and architectural choices are captured as OpenSpec change proposals under openspec/changes/<change-id>/proposal.md. proposal.md is the only required artifact; specs/tasks/design are optional per-change. See openspec/README.md for the convention and openspec/changes/pick-adr-methodology/proposal.md for the rationale. Validate with openspec validate <change-id> --type change --strict.
- When opening a PR via
gh pr create --body, fill the body from.github/PULL_REQUEST_TEMPLATE.md— the--bodyflag bypasses the template that GitHub's web UI auto-loads.
When reviewing a pull request, agents are encouraged to launch their available review tooling and surface findings to the contributor. Scope reviews to the PR's changed files unless instructed otherwise. Findings are advisory — the contributor decides whether and how to act on them. We do suggest addressing the most destructive findings (bugs, security issues, data-loss risks) before merging.
Recommended: check whether the PR's changed files appear in any per-file ignore block (like eslint.config.mjs). For overlapping files, suggest fixing existing violations and removing the file from the ignore list — opportunistic cleanup, not a blocker. Flag any new violations added in the same file: the ignore list exempts existing code, not new additions.
Recommended: when the diff includes files under openspec/, focus on semantic quality of the rationale — CI already covers well-formedness via pnpm openspec:validate. Flag: ## Why sections that don't list alternatives or the trade-off; requirement scenarios too vague to fail when violated; proposals re-asking a question settled by an earlier change. Do NOT flag: missing proposals on code-only PRs (non-trivial is the author's judgement call, not an automated gate); absence of optional artifacts (tasks.md, design.md, secondary specs); proposals lacking tests or implementation detail (proposals capture rationale, not feature specs).
Tools wired up to read these rules:
- Claude Code — reads
AGENTS.mdat project root alongsideCLAUDE.md - Greptile — auto-indexes
AGENTS.mdfor PR reviews - Codex (OpenAI) — reads
AGENTS.mdat project root - Cursor — reads
AGENTS.mdat project root - Zed — reads
AGENTS.mdat project root - opencode — reads
AGENTS.mdat project root - GitHub Copilot — reads
.github/copilot-instructions.md, symlinked toAGENTS.md