- **DRY principle**: Always follow the DRY principle when possible. Never repeat UI elements across views—extract them into reusable components in `src/components/`. Same applies to logic—extract into custom hooks in `src/hooks/`.
When you need documentation for libraries like **plebbit-react-hooks** or **plebbit-js**, use the Context7 skill to fetch current docs instead of relying on potentially outdated training data.
Use **playwright-cli** for browser automation—navigation, form filling, screenshots, testing, and data extraction. The CLI + skill approach is token-efficient: it avoids loading large MCP tool schemas and verbose accessibility trees into context.
**Do NOT use browser MCPs** (cursor-ide-browser, playwright-mcp, chrome MCP, etc.) for this project. MCP servers inject heavy tool definitions and page snapshots into the context window, degrading quality and response speed.
**Install** (globally, once per machine). Agents working on this project without playwright-cli should run:
```bash
npm install -g @playwright/cli@latest
```
Then from the project root, install the skill so the agent can use it:
```bash
playwright-cli install --skills
```
The skill installs to `.cursor/skills/playwright-cli/` (or `.claude/skills/` for Claude Code). Agents invoke commands via Bash (e.g. `playwright-cli open`, `playwright-cli snapshot`, `playwright-cli click e1`).
If you're using an AI coding assistant (Cursor, Claude Code, Codex, etc.), set up hooks to automatically enforce code quality. Most modern AI agents support lifecycle hooks.
### Recommended Hooks
Set up these hooks for this project:
| Hook | Command | Purpose |
|------|---------|---------|
| `afterFileEdit` | `npx oxfmt <file>` | Auto-format files after AI edits |
Use the **`gh` CLI** for all GitHub operations (issues, PRs, actions, dependabot, projects, search, etc.). For anything without a dedicated subcommand, `gh api` can call any GitHub REST endpoint directly. Use `--json` + `--jq` to keep output minimal.
**Do NOT use the GitHub MCP server.** It injects ~40 tool definitions into the context window on every message, wasting tokens even when you're not doing GitHub operations.
Each MCP server injects its tool definitions into the context window, consuming tokens even when the tools aren't being used. Too many servers degrade response quality, cause the agent to "forget" earlier context, and slow down responses. If you notice many MCP tools in your context, warn the user and suggest disabling unused ones.
- **Title**: Use [Conventional Commits](https://www.conventionalcommits.org/) style. Use `perf` for performance optimizations (not `fix`). Keep it short. **MUST be wrapped in backticks.**
- **Description**: Optional. 2-3 informal sentences describing the solution (not the problem). Concise, technical, no bullet points. Use backticks for code references.
When proposing or implementing code changes, always suggest a GitHub issue to track the problem. Format:
- **Title**: As short as possible. **MUST be wrapped in backticks.**
- **Description**: 2-3 informal sentences describing the problem (not the solution). Write as if the issue hasn't been fixed yet. Use backticks for code references.
> - **Description:** Comment timestamps show incorrect timezones when users view posts from different regions. The `formatDate()` function doesn't account for user's local timezone settings.
When the user reports a bug in a specific file, or asks you to verify a possible issue in a specific file/code block/line, **always start by checking the git history for that code before making any changes**. This is the mandatory first step of any bug investigation.
**Why:** A previous contributor may have intentionally written the code that way to fix a different bug, handle an edge case, or work around a library limitation. Blindly "fixing" it without this context risks reintroducing old bugs.
**Workflow:**
1. **Scan recent commit titles (titles only).** Use `git log --oneline` scoped to the relevant file or line range to get a quick overview without wasting tokens on full diffs:
2. **Dig into relevant commits only.** If any commit title looks related to the bug being investigated (e.g., mentions the same feature, component, or behavior), then read its full message and diff — but **only for that file**, to keep token usage minimal:
```bash
# Show commit message + diff scoped to the specific file only
git show <commit-hash> -- path/to/file.tsx
```
Skip this step for commits whose titles are clearly unrelated.
3. **Proceed with the rest of the investigation.** Only after understanding the git context, move on to reading the code, reproducing the bug, checking related files, etc.
**Do NOT skip step 1.** Even if the fix seems obvious, the git history may reveal constraints you're not aware of.
When adding or updating npm packages, **always use exact version numbers**—never use carets (`^`) or tildes (`~`).
```bash
# ✅ Correct
yarn add lodash@4.17.21
# ❌ Wrong (will add caret by default)
yarn add lodash
```
**Why pin versions:**
- **Supply chain security**: A compromised package could push a malicious minor/patch update. With carets, running `yarn upgrade` or regenerating `yarn.lock` would auto-install it.
- **Reproducibility**: Guarantees identical dependencies across all environments.
- **Defense in depth**: While `yarn.lock` pins versions in practice, explicit pinning in `package.json` protects against lockfile regeneration and makes the intended version auditable.
**When upgrading packages:**
1. Specify the exact version: `yarn add package@1.2.3`
2. Review the changelog for breaking changes or security notes
3. Test the upgrade before committing
**Note:** This applies to both `dependencies` and `devDependencies`. There are no exceptions—the convenience of auto-updates doesn't justify the security risk.
Delegate heavy work to subprocesses (subagents, background tasks, etc.) to avoid filling the main context window with build logs, test output, and browser snapshots.
- One focused task per subprocess — don't overload a single one
- The main agent orchestrates; subprocesses do the heavy lifting
- For complex problems, run multiple subprocesses in parallel
**Note:** These guidelines are universal and tool-agnostic. This is a FOSS project — contributors use different AI tools (Cursor, Claude Code, Codex, etc.) each with their own subprocess/subagent systems. AGENTS.md describes *what* to do (verify, delegate, loop), not *how* your specific tool implements it. If your tool supports custom subagent definitions (e.g. `.cursor/agents/`, `.claude/agents/`), configure them locally — they're gitignored and won't be shared.