diff --git a/.agents/skills/oxfmt/SKILL.md b/.agents/skills/oxfmt/SKILL.md new file mode 100644 index 0000000..80e8be8 --- /dev/null +++ b/.agents/skills/oxfmt/SKILL.md @@ -0,0 +1,246 @@ +--- +name: oxfmt +description: Run and configure oxfmt — the high-performance JavaScript/TypeScript formatter built on the Oxc compiler stack, ~30x faster than Prettier. Use this skill whenever working in a project that has oxfmt installed (check for `oxfmt` in package.json devDependencies or an `.oxfmtrc.json` / `.oxfmtrc.jsonc` config file). This includes when you need to format code after making changes, set up oxfmt in a new project, migrate from Prettier, configure formatting rules, set up editor integration (VS Code, Neovim, Zed, JetBrains), or add formatting checks to CI/CD pipelines. Also use when the user mentions "oxfmt", "oxc formatter", "format with oxc", or asks about Prettier alternatives with better performance. +--- + +# Oxfmt — The Oxc Formatter + +Oxfmt is a Prettier-compatible formatter for the JavaScript ecosystem. It currently passes ~95% of Prettier's JS/TS test suite. It formats JavaScript, JSX, TypeScript, TSX, JSON, JSONC, JSON5, YAML, TOML, HTML, Angular, Vue, CSS, SCSS, Less, Markdown, MDX, GraphQL, Ember, and Handlebars. + +## When to use oxfmt + +- After modifying code in a project that has oxfmt installed +- Setting up formatting in a new JS/TS project +- Migrating from Prettier to oxfmt +- Configuring formatting rules, editor integration, or CI checks + +## Quick reference + +### Installation + +```bash +# Pick your package manager +npm add -D oxfmt +pnpm add -D oxfmt +yarn add -D oxfmt +bun add -D oxfmt +``` + +Add scripts to `package.json`: +```json +{ + "scripts": { + "fmt": "oxfmt", + "fmt:check": "oxfmt --check" + } +} +``` + +Running `oxfmt` with no arguments formats the current directory (like `prettier --write .`). + +### CLI flags + +| Flag | Purpose | +|------|---------| +| `--check` | Check formatting without writing (exit 1 if unformatted) | +| `--list-different` | List files that would change | +| `--write` | Format and write in place (default) | +| `--init` | Create `.oxfmtrc.json` with defaults | +| `--migrate=prettier` | Convert `.prettierrc` to `.oxfmtrc.json` | +| `--migrate=biome` | Convert Biome config to `.oxfmtrc.json` | +| `-c PATH` | Use a specific config file | +| `--ignore-path PATH` | Custom ignore file (repeatable) | +| `--with-node-modules` | Include `node_modules/` (skipped by default) | +| `--no-error-on-unmatched-pattern` | Don't fail on unmatched globs | +| `--stdin-filepath PATH` | Format stdin, using PATH to infer parser | +| `--threads N` | Thread count (set to 1 for single core) | +| `--lsp` | Start the LSP server (used by editors) | + +CLI does **not** support formatting options as flags (e.g., no `--no-semi`). Use the config file instead — this keeps formatting consistent across CLI, editors, and CI. + +### Configuration + +Oxfmt looks for `.oxfmtrc.json` or `.oxfmtrc.jsonc` starting from the current directory, walking up. + +Generate a starter config: +```bash +oxfmt --init +``` + +#### Core options + +```jsonc +{ + "$schema": "./node_modules/oxfmt/configuration_schema.json", + "printWidth": 100, // Line width limit (default: 100, Prettier default is 80) + "tabWidth": 2, // Spaces per indent level + "useTabs": false, // Tabs vs spaces + "semi": true, // Semicolons + "singleQuote": false, // Quote style + "trailingComma": "all", // Trailing commas in multi-line + "insertFinalNewline": true +} +``` + +Note: oxfmt defaults `printWidth` to 100, while Prettier defaults to 80. If migrating, decide which you prefer. + +#### Per-file overrides + +```json +{ + "printWidth": 100, + "overrides": [ + { + "files": ["*.test.js", "*.spec.ts"], + "options": { "printWidth": 120 } + }, + { + "files": ["*.json"], + "excludeFiles": ["package.json"], + "options": { "tabWidth": 4 } + } + ] +} +``` + +#### Built-in features + +These are disabled by default but can be enabled in the config: + +- **`sortImports`** — Sorts import statements +- **`sortTailwindcss`** — Sorts Tailwind CSS classes +- **`sortPackageJson`** — Sorts `package.json` fields (enabled by default) + +#### Ignore patterns + +Add `ignorePatterns` in the config file, or use a `.oxfmtignore` / `.prettierignore` file: +```json +{ + "ignorePatterns": ["dist/", "coverage/", "*.min.js"] +} +``` + +#### .editorconfig support + +Oxfmt reads these `.editorconfig` properties (nearest file only, no merging): +- `end_of_line` → `endOfLine` +- `indent_style` → `useTabs` +- `indent_size` → `tabWidth` +- `max_line_length` → `printWidth` +- `insert_final_newline` → `insertFinalNewline` + +### Migrating from Prettier + +```bash +# Install oxfmt +pnpm add -D oxfmt + +# Auto-convert .prettierrc → .oxfmtrc.json +oxfmt --migrate=prettier + +# Format everything so the diff is clean +pnpm oxfmt + +# Replace Prettier scripts in package.json +# "prettier --write ." → "oxfmt" +# "prettier --check ." → "oxfmt --check" +``` + +After migration, review the generated `.oxfmtrc.json` — especially `printWidth` since the default changed from 80 to 100. + +### Editor integration + +Editor extensions use the local `oxfmt --lsp`, so oxfmt must be installed in the project. + +**VS Code / Cursor:** +Install the "Oxc" extension from the VS Code Marketplace. Recommended team setup: + +`.vscode/extensions.json`: +```json +{ "recommendations": ["oxc.oxc-vscode"] } +``` + +`.vscode/settings.json`: +```json +{ + "editor.defaultFormatter": "oxc.oxc-vscode", + "editor.formatOnSave": true +} +``` + +**Zed:** Install the oxc extension from Zed's marketplace. + +**JetBrains (IntelliJ / WebStorm):** Install from JetBrains Marketplace. + +**Neovim:** +- With nvim-lspconfig: `npm i -g oxfmt` then `vim.lsp.enable('oxfmt')` +- With conform.nvim: set `formatters_by_ft` for js/ts/json/vue +- With coc.nvim: `:CocInstall coc-oxc` + +**Other LSP-compatible editors (Emacs, Helix, Sublime):** Point at `oxfmt --lsp`. + +**Non-LSP editors:** Pipe via stdin: `cat file.js | oxfmt --stdin-filepath file.js` + +### CI setup + +**GitHub Actions:** +```yaml +jobs: + format: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v6 + with: + node-version: lts/* + cache: pnpm + - run: pnpm install --frozen-lockfile + - run: pnpm run fmt:check +``` + +**GitLab CI:** +```yaml +oxfmt: + image: node:lts + stage: test + before_script: + - npm install + script: + - npm run fmt:check +``` + +**Autofix (GitHub):** Use [autofix.ci](https://autofix.ci) — run `oxfmt` (no `--check`) and let the action commit fixes. + +### Pre-commit hook (lint-staged) + +```json +{ + "lint-staged": { + "*": "oxfmt --no-error-on-unmatched-pattern" + } +} +``` + +Use `--no-error-on-unmatched-pattern` so non-supported file types don't cause errors. + +### Node.js API + +```js +import { format } from "oxfmt"; + +const result = format("foo.ts", "const x:string = 1", { + semi: false, + singleQuote: true, +}); +console.log(result); // const x: string = 1 +``` + +## Workflow after code changes + +When you've modified files in an oxfmt-enabled project: + +1. Run `pnpm oxfmt` (or the project's fmt script) to format changed files +2. If in CI or a check context, use `--check` instead to verify without writing + +The formatter is fast enough to run on the entire project — no need to target individual files unless piping via stdin. diff --git a/.agents/skills/oxlint/SKILL.md b/.agents/skills/oxlint/SKILL.md new file mode 100644 index 0000000..b883b56 --- /dev/null +++ b/.agents/skills/oxlint/SKILL.md @@ -0,0 +1,230 @@ +--- +name: oxlint +description: "Run and configure oxlint — the high-performance JavaScript/TypeScript linter built on the Oxc compiler stack. Use this skill whenever working in a project that has oxlint installed (check for `oxlint` in package.json devDependencies or an `.oxlintrc.json` / `oxlint.config.ts` config file). This includes when you need to lint code after making changes, fix linting errors, configure oxlint rules/plugins, set up or modify `.oxlintrc.json`, or migrate from ESLint." +--- + +# Oxlint — High-Performance JS/TS Linter + +Oxlint is 50-100x faster than ESLint. It ships with 690+ rules covering ESLint core, TypeScript, React, Jest, Unicorn, jsx-a11y, and more. It prioritizes high-signal correctness checks by default — things that are incorrect, unsafe, or useless — so teams can adopt it without drowning in false positives. + +## Detection + +Before linting, confirm the project uses oxlint by checking for any of: +- `oxlint` in `package.json` devDependencies/dependencies +- An `.oxlintrc.json` file in the project root +- An `oxlint.config.ts` file in the project root +- An `oxlint` or `lint` script in `package.json` that references `oxlint` + +If none of these exist, the project doesn't use oxlint — don't run it. + +## Running Oxlint + +### After code changes +Run oxlint to check your work. Prefer the project's npm script if one exists: + +```bash +# If package.json has a lint script using oxlint +npm run lint + +# Otherwise, run directly +npx oxlint +``` + +### Fixing issues automatically +```bash +npx oxlint --fix +``` + +Use `--fix` for safe automatic fixes. Avoid `--fix-dangerously` unless the user explicitly asks for it — it can apply unsafe transformations. + +### Linting specific files +After editing only a few files, you can lint just those: +```bash +npx oxlint src/components/Button.tsx src/utils/helpers.ts +``` + +### Interpreting output +Oxlint prints diagnostics with rule names in parentheses, e.g. `(no-unused-vars)`. When fixing: +1. Read the diagnostic message carefully — oxlint gives precise, actionable information +2. Fix the underlying code issue rather than suppressing the rule +3. Only add `// oxlint-ignore` comments as a last resort when the diagnostic is a genuine false positive + +### Output formats +For CI or tooling integration: +```bash +npx oxlint --format json # Machine-readable JSON +npx oxlint --format github # GitHub Actions annotations +npx oxlint --format unix # Simple one-line-per-error format +``` + +## Configuration + +### Creating a config +```bash +npx oxlint --init +``` +This generates an `.oxlintrc.json` starter config. + +### Config file format (.oxlintrc.json) +The config uses JSONC (JSON with comments). Key sections: + +```jsonc +{ + // Enable/disable individual rules with severity levels + "rules": { + "no-unused-vars": "error", + "no-console": "warn", + "no-plusplus": ["error", { "allowForLoopAfterthoughts": true }] + }, + + // Enable groups of related rules by category + "categories": { + "correctness": "error", // Definitely-wrong code + "suspicious": "warn", // Probably-wrong code + "pedantic": "off", // Opinionated style checks + "perf": "warn", // Performance anti-patterns + "style": "off", // Cosmetic preferences + "restriction": "off", // Extra-strict rules (opt-in) + "nursery": "off" // Unstable/experimental rules + }, + + // Plugins to enable (setting this overwrites defaults, so list all you want) + "plugins": ["typescript", "unicorn", "oxc"], + + // File-specific overrides + "overrides": [ + { + "files": ["**/*.test.{ts,tsx}"], + "rules": { "no-console": "off" } + }, + { + "files": ["scripts/**"], + "rules": { "no-console": "off" } + } + ], + + // Environment globals + "env": { + "browser": true, + "node": true + }, + + // Plugin-wide settings + "settings": { + "react": { + "linkComponents": [{ "name": "Link", "linkAttribute": "to" }] + }, + "jsx-a11y": { + "components": { "Link": "a", "Button": "button" } + } + }, + + // Type-aware linting (requires tsconfig) + "options": { + "typeAware": true + } +} +``` + +### Rule severity levels +- `"off"` / `"allow"` — Disable the rule +- `"warn"` — Report but don't fail the build +- `"error"` / `"deny"` — Report and exit non-zero + +Unique rule names can omit plugin prefix: `"no-console"` = `"eslint/no-console"`. + +### Categories +Categories group rules by intent. The recommended starting point: +- `correctness: "error"` — Always on. Catches real bugs. +- `suspicious: "warn"` — Good signal, occasionally noisy. +- Everything else: enable incrementally as the team is ready. + +### Available plugins +**Enabled by default:** `typescript`, `unicorn`, `oxc` + +**Opt-in (CLI flags or config):** +| Plugin | CLI flag | Purpose | +|--------|----------|---------| +| react | `--react-plugin` | React-specific rules | +| jsx-a11y | `--jsx-a11y-plugin` | Accessibility rules for JSX | +| nextjs | `--nextjs-plugin` | Next.js best practices | +| import | `--import-plugin` | Import/export validation | +| jest | `--jest-plugin` | Jest testing rules | +| vitest | `--vitest-plugin` | Vitest testing rules | +| jsdoc | `--jsdoc-plugin` | JSDoc documentation rules | +| node | `--node-plugin` | Node.js-specific rules | +| promise | `--promise-plugin` | Promise best practices | +| react-perf | `--react-perf-plugin` | React performance rules | +| vue | `--vue-plugin` | Vue.js rules | + +To disable a default plugin: `--disable-typescript-plugin`, `--disable-unicorn-plugin`, `--disable-oxc-plugin`. + +### Extending shared configs +```jsonc +{ + "extends": ["./configs/base.json", "./configs/frontend.json"] +} +``` +Later entries override earlier ones. Paths resolve relative to the declaring config. + +### Monorepo support +Oxlint supports nested configs. Each directory can have its own `.oxlintrc.json` that overrides parent settings. Disable with `--disable-nested-config` if unwanted. + +## CLI Quick Reference + +| Flag | What it does | +|------|-------------| +| `-c, --config=PATH` | Use a specific config file | +| `--tsconfig=PATH` | TypeScript config for path aliases | +| `--fix` | Auto-fix safe issues | +| `--fix-suggestions` | Also apply suggested fixes | +| `-A, --allow=RULE` | Suppress a rule (e.g., `-A no-console`) | +| `-W, --warn=RULE` | Warn on a rule | +| `-D, --deny=RULE` | Error on a rule | +| `--quiet` | Suppress warnings, show only errors | +| `--deny-warnings` | Treat warnings as errors (exit non-zero) | +| `--max-warnings=N` | Fail if more than N warnings | +| `-f, --format=FMT` | Output format: default, json, github, unix, etc. | +| `--ignore-pattern=PAT` | Exclude files matching pattern | +| `--type-aware` | Enable type-informed rules (needs tsconfig) | +| `--print-config` | Show resolved config (useful for debugging) | +| `--rules` | List all available rules | + +Categories can also be used with `-A`/`-W`/`-D`: +```bash +npx oxlint -D correctness -W suspicious -A pedantic +``` + +## Suppressing rules inline + +```js +// oxlint-ignore no-console -- needed for debug logging +console.log(debugInfo); + +// oxlint-ignore-next-line no-unused-vars +const _placeholder = computeValue(); +``` + +Use `oxlint-ignore` (not `eslint-disable`) — oxlint recognizes both, but prefer its native syntax. + +## Migrating from ESLint + +If the project is moving from ESLint to oxlint: + +1. **Side-by-side approach** — Run both linters, with `eslint-plugin-oxlint` disabling rules that oxlint already covers: + ```bash + npm install -D eslint-plugin-oxlint + ``` + Add it as the last plugin in your ESLint config. + +2. **Full replacement** — Use `@oxlint/migrate` to convert your ESLint config: + ```bash + npx @oxlint/migrate + ``` + This generates an `.oxlintrc.json` from your existing ESLint configuration. + +## Supported file types + +`.js`, `.mjs`, `.cjs`, `.ts`, `.mts`, `.cts`, `.jsx`, `.tsx`, `.vue`, `.svelte`, `.astro` + +For `.vue`, `.svelte`, and `.astro` files, oxlint lints only the `